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. 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 26 import java.io.File; 27 import java.nio.file.Files; 28 import java.nio.file.Path; 29 import java.nio.file.Paths; 30 import java.nio.file.StandardCopyOption; 31 import java.util.ArrayList; 32 import java.util.List; 33 import java.util.stream.Stream; 34 35 import jdk.testlibrary.JDKToolFinder; 36 37 import static jdk.testlibrary.ProcessTools.executeCommand; 38 39 /* 40 * Base class for tests. 41 * The tests focuse on that LoggerFinder works well in jigsaw environment, 42 * i.e. make sure correct Logger can be retrieved, 43 * also verify that basic functionality of retrieved Logger's works well. 44 * 45 * Note: As the test will take long time, to avoid timeout, 46 * split it as several tests, this class is the base class for tests. 47 */ 48 public class Base { 49 protected static final String JAVA_HOME = System.getProperty("java.home"); 50 protected static final Path JDK_IMAGE = Paths.get(JAVA_HOME); 51 protected static final Path JMODS = Paths.get(JAVA_HOME, "jmods"); 52 53 protected static final String TEST_SRC = System.getProperty("test.src"); 54 55 // logger client to get logger from java.base module, it should get a lazy logger 56 // which wraps the underlying real logger implementation 57 protected static final Path SRC_PATCHED_USAGE = 58 Paths.get(TEST_SRC, "patched_usage", "java.base"); 59 protected static final Path DEST_PATCHED_USAGE = Paths.get("patched_usage", "java.base"); 60 protected static final Path SRC_PATCHED_CLIENT = Paths.get(TEST_SRC, "patched_client"); 61 protected static final Path DEST_PATCHED_CLIENT = Paths.get("patched_client"); 62 63 // logger client to get logger from bootclasspath/a, it should get a lazy logger 64 // which wraps the underlying real logger implementation 65 protected static final Path SRC_BOOT_USAGE = Paths.get(TEST_SRC, "boot_usage"); 66 protected static final Path DEST_BOOT_USAGE = Paths.get("boot_usage"); 67 protected static final Path SRC_BOOT_CLIENT = Paths.get(TEST_SRC, "boot_client"); 68 protected static final Path DEST_BOOT_CLIENT = Paths.get("boot_client"); 69 70 // logger provider in named module m.l.a 71 protected static final Path SRC_NAMED_LOGGER = Paths.get(TEST_SRC, "named_logger"); 72 protected static final Path DEST_NAMED_LOGGER = Paths.get("mods_named_logger"); 73 74 // logger provider in unnamed module 75 protected static final Path SRC_UNNAMED_LOGGER = Paths.get(TEST_SRC, "unnamed_logger"); 76 protected static final Path DEST_UNNAMED_LOGGER = Paths.get("cp_unnamed_logger"); 77 protected static final Path SRC_UNNAMED_LOGGER_SERVICE_FILE = 78 SRC_UNNAMED_LOGGER.resolve("META-INF/services/java.lang.System$LoggerFinder"); 79 protected static final Path DEST_UNNAMED_LOGGER_SERVICE_DIR = 80 DEST_UNNAMED_LOGGER.resolve("META-INF/services"); 81 protected static final Path DEST_UNNAMED_LOGGER_SERVICE_FILE = 82 DEST_UNNAMED_LOGGER.resolve("META-INF/services/java.lang.System$LoggerFinder"); 83 84 // logger client in named module m.t.a 85 protected static final Path SRC_NAMED_CLIENT = Paths.get(TEST_SRC, "named_client"); 86 protected static final Path DEST_NAMED_CLIENT = Paths.get("mods_named_client"); 87 88 // logger client in unnamed module 89 protected static final Path SRC_UNNAMED_CLIENT = Paths.get(TEST_SRC, "unnamed_client"); 90 protected static final Path DEST_UNNAMED_CLIENT = Paths.get("cp_unnamed_client"); 91 92 // customized image with only module java.base 93 protected static final Path IMAGE = Paths.get("image"); 94 // customized image with java.base and logger provider module m.l.a 95 protected static final Path IMAGE_LOGGER = Paths.get("image_logger"); 96 // customized image with module java.base and logger client module m.t.a 97 protected static final Path IMAGE_CLIENT = Paths.get("image_client"); 98 // customized image with module java.base, logger provider module m.l.a 99 // and logger client module m.t.a 100 protected static final Path IMAGE_CLIENT_LOGGER = Paths.get("image_all"); 101 102 // lazy logger class which wraps the underlying real logger implementation 103 protected static final String LAZY_LOGGER = 104 "jdk.internal.logger.LazyLoggers$JdkLazyLogger"; 105 // JUL logger class which wraps java.util.logging.Logger 106 protected static final String JUL_LOGGER = 107 "sun.util.logging.internal.LoggingProviderImpl$JULWrapper"; 108 // default simple logger class when no logger provider can be found 109 protected static final String SIMPLE_LOGGER = 110 "jdk.internal.logger.SimpleConsoleLogger"; 111 // logger class in named module m.l.a 112 protected static final String LOGGER_A = "pkg.a.l.LoggerA"; 113 // logger class in unnamed module m.l.b 114 protected static final String LOGGER_B = "pkg.b.l.LoggerB"; 115 116 // logger client in named module 117 protected static final String CLIENT_A = "m.t.a/pkg.a.t.TestA"; 118 // logger client in unnamed module 119 protected static final String CLIENT_B = "pkg.b.t.TestB"; 120 // logger client which gets logger through boot class BootUsage 121 protected static final String BOOT_CLIENT = "BootClient"; 122 // logger client which gets logger through patched class 123 // java.base/java.lang.PatchedUsage 124 protected static final String PATCHED_CLIENT = "PatchedClient"; 125 126 protected void setupAllClient() throws Throwable { 127 // compiles logger client which will get logger through patched 128 // class java.base/java.lang.PatchedUsage 129 compile(SRC_BOOT_USAGE, DEST_BOOT_USAGE); 130 compile(SRC_BOOT_CLIENT, DEST_BOOT_CLIENT, 131 "--class-path", DEST_BOOT_USAGE.toString()); 132 133 // compiles logger client which will get logger through boot 134 // class BootUsage 135 compile(SRC_PATCHED_USAGE, DEST_PATCHED_USAGE, 136 "--patch-module", "java.base=" + SRC_PATCHED_USAGE.toString()); 137 compile(SRC_PATCHED_CLIENT, DEST_PATCHED_CLIENT, 138 "--patch-module", "java.base=" + DEST_PATCHED_USAGE.toString()); 139 140 // compiles logger client in unnamed module 141 compile(SRC_UNNAMED_CLIENT, DEST_UNNAMED_CLIENT, 142 "--source-path", SRC_UNNAMED_CLIENT.toString()); 143 144 // compiles logger client in named module m.t.a 145 compile(SRC_NAMED_CLIENT, DEST_NAMED_CLIENT, 146 "--module-source-path", SRC_NAMED_CLIENT.toString()); 147 } 148 149 protected void setupNamedLogger() throws Throwable { 150 // compiles logger provider in named module m.l.a 151 compile(SRC_NAMED_LOGGER, DEST_NAMED_LOGGER, 152 "--module-source-path", SRC_NAMED_LOGGER.toString()); 153 } 154 155 protected void setupUnnamedLogger() throws Throwable { 156 // compiles logger provider in unnamed module 157 compile(SRC_UNNAMED_LOGGER, DEST_UNNAMED_LOGGER, 158 "--source-path", SRC_UNNAMED_LOGGER.toString()); 159 Files.createDirectories(DEST_UNNAMED_LOGGER_SERVICE_DIR); 160 Files.copy(SRC_UNNAMED_LOGGER_SERVICE_FILE, DEST_UNNAMED_LOGGER_SERVICE_FILE, 161 StandardCopyOption.REPLACE_EXISTING); 162 } 163 164 protected boolean checkJMODS() throws Throwable { 165 // if $JAVA_HOME/jmods does not exist, skip below steps 166 // as there is no way to build customized images by jlink 167 if (Files.notExists(JMODS)) { 168 System.err.println("Skip tests which require image"); 169 return false; 170 } 171 return true; 172 } 173 174 protected void setupJavaBaseImage() throws Throwable { 175 if (!checkJMODS()) { 176 return; 177 } 178 179 // build image with just java.base module 180 String mpath = JMODS.toString(); 181 execTool("jlink", 182 "--module-path", mpath, 183 "--add-modules", "java.base", 184 "--output", IMAGE.toString()); 185 } 186 187 protected void setupLoggerImage() throws Throwable { 188 if (!checkJMODS()) { 189 return; 190 } 191 192 // build image with java.base + m.l.a modules 193 String mpath = DEST_NAMED_LOGGER.toString() + File.pathSeparator + JMODS.toString(); 194 execTool("jlink", 195 "--module-path", mpath, 196 "--add-modules", "m.l.a", 197 "--output", IMAGE_LOGGER.toString()); 198 } 199 200 protected void setupClientImage() throws Throwable { 201 if (!checkJMODS()) { 202 return; 203 } 204 205 // build image with java.base + m.t.a modules 206 String mpath = DEST_NAMED_CLIENT.toString() + File.pathSeparator + JMODS.toString(); 207 execTool("jlink", 208 "--module-path", mpath, 209 "--add-modules", "m.t.a", 210 "--output", IMAGE_CLIENT.toString()); 211 } 212 213 protected void setupFullImage() throws Throwable { 214 if (!checkJMODS()) { 215 return; 216 } 217 218 // build image with java.base + m.l.a + m.t.a modules 219 String mpath = DEST_NAMED_LOGGER.toString() + File.pathSeparator 220 + DEST_NAMED_CLIENT.toString() + File.pathSeparator + JMODS.toString(); 221 execTool("jlink", 222 "--module-path", mpath, 223 "--add-modules", "m.l.a,m.t.a", 224 "--output", IMAGE_CLIENT_LOGGER.toString()); 225 226 } 227 228 protected static void assertTrue(boolean b) { 229 if (!b) { 230 throw new RuntimeException("expected true, but get false."); 231 } 232 } 233 234 /* 235 * run test with supplied java image which could be jdk image or customized image 236 */ 237 protected void runTest(Path image, String... opts) throws Throwable { 238 String[] options = Stream.concat(Stream.of(getJava(image)), Stream.of(opts)) 239 .toArray(String[]::new); 240 241 ProcessBuilder pb = new ProcessBuilder(options); 242 int exitValue = executeCommand(pb).outputTo(System.out) 243 .errorTo(System.err) 244 .getExitValue(); 245 assertTrue(exitValue == 0); 246 } 247 248 private void compile(Path src, Path dest, String... params) throws Throwable { 249 assertTrue(CompilerUtils.compile(src, dest, params)); 250 } 251 252 private String getJava(Path image) { 253 boolean isWindows = System.getProperty("os.name").startsWith("Windows"); 254 Path java = image.resolve("bin").resolve(isWindows ? "java.exe" : "java"); 255 if (Files.notExists(java)) 256 throw new RuntimeException(java + " not found"); 257 return java.toAbsolutePath().toString(); 258 } 259 260 private void execTool(String tool, String... args) throws Throwable { 261 String path = JDKToolFinder.getJDKTool(tool); 262 List<String> commands = new ArrayList<>(); 263 commands.add(path); 264 Stream.of(args).forEach(commands::add); 265 ProcessBuilder pb = new ProcessBuilder(commands); 266 267 int exitValue = executeCommand(pb).outputTo(System.out) 268 .errorTo(System.out) 269 .shouldNotContain("no module is recorded in hash") 270 .getExitValue(); 271 assertTrue(exitValue == 0); 272 } 273 }