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 38 import org.testng.annotations.BeforeTest; 39 import org.testng.annotations.Test; 40 import static org.testng.Assert.*; 41 42 /** 43 * @test 44 * @bug 8174826 45 * @library /lib/testlibrary 46 * @modules jdk.charsets jdk.compiler jdk.jlink 47 * @build SuggestProviders CompilerUtils 48 * @run testng SuggestProviders 49 */ 50 51 public class SuggestProviders { 52 private static final String JAVA_HOME = System.getProperty("java.home"); 53 private static final String TEST_SRC = System.getProperty("test.src"); 54 55 private static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); 56 private static final Path MODS_DIR = Paths.get("mods"); 57 58 private static final String MODULE_PATH = 59 Paths.get(JAVA_HOME, "jmods").toString() + 60 File.pathSeparator + MODS_DIR.toString(); 61 62 // the names of the modules in this test 63 private static String[] modules = new String[] {"m1", "m2", "m3", "m4"}; 64 65 66 private static boolean hasJmods() { 67 if (!Files.exists(Paths.get(JAVA_HOME, "jmods"))) { 68 System.err.println("Test skipped. NO jmods directory"); 69 return false; 70 } 71 return true; 72 } 73 74 /* 75 * Compiles all modules used by the test 76 */ 77 @BeforeTest 78 public void compileAll() throws Throwable { 79 if (!hasJmods()) return; 80 81 for (String mn : modules) { 82 Path msrc = SRC_DIR.resolve(mn); 83 assertTrue(CompilerUtils.compile(msrc, MODS_DIR, 84 "--module-source-path", SRC_DIR.toString())); 85 } 86 } 87 88 @Test 89 public void suggestProviders() throws Throwable { 90 if (!hasJmods()) return; 91 92 List<String> output = JLink.run("--module-path", MODULE_PATH, 93 "--add-modules", "m1", 94 "--suggest-providers").output(); 95 // check a subset of services used by java.base 96 List<String> expected = List.of( 97 "uses java.lang.System$LoggerFinder", 98 "uses java.net.ContentHandlerFactory", 99 "uses java.net.spi.URLStreamHandlerProvider", 100 "uses java.nio.channels.spi.AsynchronousChannelProvider", 101 "uses java.nio.channels.spi.SelectorProvider", 102 "uses java.nio.charset.spi.CharsetProvider", 103 "uses java.nio.file.spi.FileSystemProvider", 104 "uses java.nio.file.spi.FileTypeDetector", 105 "uses java.security.Provider", 106 "uses java.util.spi.ToolProvider", 107 "uses p1.S", 108 "module jdk.charsets provides java.nio.charset.spi.CharsetProvider, used by java.base", 109 "module jdk.compiler provides java.util.spi.ToolProvider, used by java.base", 110 "module jdk.jlink provides java.util.spi.ToolProvider, used by java.base", 111 "module m1 provides p1.S, used by m1", 112 "module m2 provides p1.S, used by m1" 113 ); 114 115 assertTrue(output.containsAll(expected)); 116 } 117 118 @Test 119 public void providersForServices() throws Throwable { 120 if (!hasJmods()) return; 121 122 List<String> output = 123 JLink.run("--module-path", MODULE_PATH, 124 "--add-modules", "m1", 125 "--suggest-providers", 126 "java.nio.charset.spi.CharsetProvider,p1.S,p2.T").output(); 127 128 System.out.println(output); 129 List<String> expected = List.of( 130 "module jdk.charsets provides java.nio.charset.spi.CharsetProvider, used by java.base", 131 "module m1 provides p1.S, used by m1", 132 "module m2 provides p1.S, used by m1", 133 "module m2 provides p2.T, used by m2", 134 "module m3 provides p2.T, used by m2" 135 ); 136 137 assertTrue(output.containsAll(expected)); 138 } 139 140 @Test 141 public void unusedService() throws Throwable { 142 if (!hasJmods()) return; 143 144 List<String> output = 145 JLink.run("--module-path", MODULE_PATH, 146 "--add-modules", "m1", 147 "--suggest-providers", 148 "nonExistentType").output(); 149 150 System.out.println(output); 151 List<String> expected = List.of( 152 "Services specified in --suggest-providers not used: nonExistentType" 153 ); 154 155 assertTrue(output.containsAll(expected)); 156 } 157 158 @Test 159 public void noSuggestProviders() throws Throwable { 160 if (!hasJmods()) return; 161 162 List<String> output = 163 JLink.run("--module-path", MODULE_PATH, 164 "--add-modules", "m1", 165 "--bind-services", 166 "--limit-modules", "m1,m2,m3,java.base", 167 "--suggest-providers").output(); 168 169 String expected = "--bind-services option is specified. No additional providers suggested."; 170 assertTrue(output.contains(expected)); 171 172 } 173 174 @Test 175 public void suggestTypeNotRealProvider() throws Throwable { 176 if (!hasJmods()) return; 177 178 List<String> output = 179 JLink.run("--module-path", MODULE_PATH, 180 "--add-modules", "m1", 181 "--suggest-providers", 182 "java.util.List").output(); 183 184 System.out.println(output); 185 List<String> expected = List.of( 186 "Services specified in --suggest-providers not used: java.util.List" 187 ); 188 189 assertTrue(output.containsAll(expected)); 190 } 191 192 // @Test @ignore JDK-8178405 193 public void noOneUsesProvider() throws Throwable { 194 if (!hasJmods()) return; 195 196 List<String> output = 197 JLink.run("--module-path", MODULE_PATH, 198 "--add-modules", "m4", 199 "--suggest-providers", 200 "p4.Impl").output(); 201 202 System.out.println(output); 203 List<String> expected = List.of( 204 "Services specified in --suggest-providers not used: p4.Impl" 205 ); 206 207 assertTrue(output.containsAll(expected)); 208 } 209 210 // @Test @ignore JDK-8178404 211 public void nonObservableModule() throws Throwable { 212 if (!hasJmods()) return; 213 214 List<String> output = 215 JLink.run(false, 216 "--module-path", MODULE_PATH, 217 "--add-modules", "nonExistentModule", 218 "--suggest-providers", 219 "java.nio.charset.spi.CharsetProvider").output(); 220 221 System.out.println(output); 222 List<String> expected = List.of( 223 "Error: Module nonExistentModule not found" 224 ); 225 226 assertTrue(output.containsAll(expected)); 227 } 228 229 static class JLink { 230 static final ToolProvider JLINK_TOOL = ToolProvider.findFirst("jlink") 231 .orElseThrow(() -> 232 new RuntimeException("jlink tool not found") 233 ); 234 235 static JLink run(String... options) { 236 return run(true, options); 237 } 238 239 static JLink run(boolean expectSuccess, String... options) { 240 JLink jlink = new JLink(); 241 if (expectSuccess){ 242 assertEquals(jlink.execute(options), 0 , 243 "Jlink failed."); 244 } 245 else { 246 assertNotEquals(jlink.execute(options), 0, 247 "Jlink succeeded. Expect to fail."); 248 } 249 return jlink; 250 } 251 252 final List<String> output = new ArrayList<>(); 253 private int execute(String... options) { 254 System.out.println("jlink " + 255 Stream.of(options).collect(Collectors.joining(" "))); 256 257 StringWriter writer = new StringWriter(); 258 PrintWriter pw = new PrintWriter(writer); 259 int rc = JLINK_TOOL.run(pw, pw, options); 260 System.out.println(writer.toString()); 261 Stream.of(writer.toString().split("\\v")) 262 .map(String::trim) 263 .forEach(output::add); 264 return rc; 265 } 266 267 boolean contains(String s) { 268 return output.contains(s); 269 } 270 271 List<String> output() { 272 return output; 273 } 274 } 275 }