1 /* 2 * Copyright (c) 2017, 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. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 import java.io.File; 25 import java.io.PrintWriter; 26 import java.io.StringWriter; 27 import java.nio.file.Files; 28 import java.nio.file.Path; 29 import java.nio.file.Paths; 30 import java.util.ArrayList; 31 import java.util.List; 32 import java.util.spi.ToolProvider; 33 import java.util.stream.Collectors; 34 import java.util.stream.Stream; 35 36 import static jdk.testlibrary.Asserts.assertTrue; 37 import static jdk.testlibrary.ProcessTools.*; 38 39 import org.testng.annotations.BeforeTest; 40 import org.testng.annotations.Test; 41 import static org.testng.Assert.*; 42 43 /** 44 * @test 45 * @bug 8174826 46 * @library /lib/testlibrary 47 * @modules jdk.compiler jdk.jlink 48 * @build BindServices CompilerUtils jdk.testlibrary.ProcessTools 49 * @run testng BindServices 50 */ 51 52 public class BindServices { 53 private static final String JAVA_HOME = System.getProperty("java.home"); 54 private static final String TEST_SRC = System.getProperty("test.src"); 55 56 private static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); 57 private static final Path MODS_DIR = Paths.get("mods"); 58 59 private static final String MODULE_PATH = 60 Paths.get(JAVA_HOME, "jmods").toString() + 61 File.pathSeparator + MODS_DIR.toString(); 62 63 // the names of the modules in this test 64 private static String[] modules = new String[] {"m1", "m2", "m3"}; 65 66 67 private static boolean hasJmods() { 68 if (!Files.exists(Paths.get(JAVA_HOME, "jmods"))) { 69 System.err.println("Test skipped. NO jmods directory"); 70 return false; 71 } 72 return true; 73 } 74 75 /* 76 * Compiles all modules used by the test 77 */ 78 @BeforeTest 79 public void compileAll() throws Throwable { 80 if (!hasJmods()) return; 81 82 for (String mn : modules) { 83 Path msrc = SRC_DIR.resolve(mn); 84 assertTrue(CompilerUtils.compile(msrc, MODS_DIR, 85 "--module-source-path", SRC_DIR.toString())); 86 } 87 } 88 89 @Test 90 public void noServiceBinding() throws Throwable { 91 if (!hasJmods()) return; 92 93 Path dir = Paths.get("noServiceBinding"); 94 95 // no service binding and does not link m2,m3 providers. 96 JLink.run("--output", dir.toString(), 97 "--module-path", MODULE_PATH, 98 "--add-modules", "m1").output(); 99 100 testImage(dir, "m1"); 101 } 102 103 @Test 104 public void fullServiceBinding() throws Throwable { 105 if (!hasJmods()) return; 106 107 Path dir = Paths.get("fullServiceBinding"); 108 109 // full service binding 110 // m2 is a provider used by m1. During service binding, when m2 is 111 // resolved, m2 uses p2.T that causes m3 to be linked as it is a 112 // provider to p2.T 113 JLink.run("--output", dir.toString(), 114 "--module-path", MODULE_PATH, 115 "--add-modules", "m1", 116 "--bind-services", 117 "--limit-modules", "m1,m2,m3,java.base"); 118 119 testImage(dir, "m1", "m2", "m3"); 120 } 121 122 @Test 123 public void testVerbose() throws Throwable { 124 if (!hasJmods()) return; 125 126 Path dir = Paths.get("verbose"); 127 128 List<String> output = 129 JLink.run("--output", dir.toString(), 130 "--module-path", MODULE_PATH, 131 "--add-modules", "m1", 132 "--bind-services", 133 "--verbose", 134 "--limit-modules", "m1,m2,m3,java.base").output(); 135 136 List<String> expected = List.of( 137 "module m1 (" + MODS_DIR.resolve("m1").toUri().toString() + ")", 138 "module m2 (" + MODS_DIR.resolve("m2").toUri().toString() + ")", 139 "module m3 (" + MODS_DIR.resolve("m3").toUri().toString() + ")", 140 "module m1 provides p1.S, used by m1", 141 "module m2 provides p1.S, used by m1", 142 "module m2 provides p2.T, used by m2", 143 "module m3 provides p2.T, used by m2" 144 ); 145 146 assertTrue(output.containsAll(expected)); 147 148 testImage(dir, "m1", "m2", "m3"); 149 } 150 151 /* 152 * Tests the given ${java.home} to only contain the specified modules 153 */ 154 private void testImage(Path javaHome, String... modules) throws Throwable { 155 Path java = javaHome.resolve("bin").resolve("java"); 156 String[] cmd = Stream.concat( 157 Stream.of(java.toString(), "-m", "m1/p1.Main"), 158 Stream.of(modules)).toArray(String[]::new); 159 160 assertTrue(executeProcess(cmd).outputTo(System.out) 161 .errorTo(System.out) 162 .getExitValue() == 0); 163 } 164 165 static class JLink { 166 static final ToolProvider JLINK_TOOL = ToolProvider.findFirst("jlink") 167 .orElseThrow(() -> 168 new RuntimeException("jlink tool not found") 169 ); 170 171 static JLink run(String... options) { 172 JLink jlink = new JLink(); 173 assertTrue(jlink.execute(options) == 0); 174 return jlink; 175 } 176 177 final List<String> output = new ArrayList<>(); 178 private int execute(String... options) { 179 System.out.println("jlink " + 180 Stream.of(options).collect(Collectors.joining(" "))); 181 182 StringWriter writer = new StringWriter(); 183 PrintWriter pw = new PrintWriter(writer); 184 int rc = JLINK_TOOL.run(pw, pw, options); 185 System.out.println(writer.toString()); 186 Stream.of(writer.toString().split("\\v")) 187 .map(String::trim) 188 .forEach(output::add); 189 return rc; 190 } 191 192 boolean contains(String s) { 193 return output.contains(s); 194 } 195 196 List<String> output() { 197 return output; 198 } 199 } 200 }