1 /* 2 * Copyright (c) 2015, 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.PrintStream; 25 import java.lang.System.Logger; 26 import java.lang.System.Logger.Level; 27 import java.util.ArrayList; 28 import java.util.concurrent.atomic.AtomicBoolean; 29 import java.util.Enumeration; 30 import java.util.List; 31 import java.util.ResourceBundle; 32 import java.util.Set; 33 import java.lang.reflect.Module; 34 import jdk.internal.logger.BootstrapLogger; 35 import jdk.internal.logger.LazyLoggers; 36 37 /* 38 * @test 39 * @bug 8144460 8144214 40 * @summary Cover the logXX and LogEvent.valueOf APIs of BootstrapLogger 41 * and logXX APIs of SimpleConsoleLogger. 42 * @modules java.base/jdk.internal.logger 43 * java.base/sun.util.logging 44 * @build BootstrapLoggerUtils LogStream 45 * @run main/othervm BootstrapLoggerAPIsTest 46 */ 47 48 public class BootstrapLoggerAPIsTest { 49 50 private static final LogStream ERR = new LogStream(); 51 52 public static void main(String[] args) throws Exception { 53 54 final ContentManager MGR = new ContentManager(); 55 56 // private reflection hook that allows us to simulate a non booted VM 57 final AtomicBoolean VM_BOOTED = new AtomicBoolean(false); 58 59 BootstrapLoggerUtils.setBootedHook(() -> VM_BOOTED.get()); 60 61 // We replace System.err to check the messages that have been logged 62 // by the JUL ConsoleHandler and default SimpleConsoleLogger 63 // implementaion 64 System.setErr(new PrintStream(ERR)); 65 66 VM_BOOTED.getAndSet(false); 67 if (BootstrapLogger.isBooted()) { 68 throw new RuntimeException("VM should not be booted!"); 69 } 70 71 final Logger LOGGER = 72 LazyLoggers.getLogger("foo.bar", Thread.class.getModule()); 73 final sun.util.logging.PlatformLogger.Level PLATFORM_LEVEL = 74 sun.util.logging.PlatformLogger.Level.SEVERE; 75 final MyResources BUNDLE = new MyResources(); 76 77 /* 78 * Test logXX APIs for interface java.lang.System.Logger. Log content 79 * before VM is booted should be retained. Log content after VM was 80 * booted should be flushed instantly. VM is not booted in first round 81 * of loop, VM is booted in second round of loop. 82 */ 83 for (int i = 0; i < 2; i++) { 84 boolean booted = BootstrapLogger.isBooted(); 85 86 // make sure there is no [remaining] content in the LogStream. 87 MGR.failLog("xyz", "throwable #", "MyClass_#", "MyMethod_#"); 88 89 /* 90 * test logXX APIs for interface java.lang.System.Logger. 91 */ 92 // void log(java.lang.System$Logger$Level,java.util.ResourceBundle, 93 // java.lang.String,java.lang.Throwable) 94 LOGGER.log(Level.ERROR, BUNDLE, "abc #0", new RuntimeException("throwable #0")); 95 MGR.checkLog(booted, "xyz #0", "throwable #0"); 96 97 // void log(java.lang.System$Logger$Level,java.util.ResourceBundle, 98 // java.lang.String,java.lang.Object[]) 99 LOGGER.log(Level.ERROR, BUNDLE, "abc #1"); 100 MGR.checkLog(booted, "xyz #1"); 101 102 // void log(java.lang.System$Logger$Level,java.lang.String,java.lang.Object[]) 103 LOGGER.log(Level.ERROR, BUNDLE, "abc {0}", "#2"); 104 MGR.checkLog(booted, "xyz #2"); 105 106 // void log(java.lang.System$Logger$Level,java.lang.String,java.lang.Throwable) 107 LOGGER.log(Level.ERROR, "xyz #3", new RuntimeException("throwable #3")); 108 MGR.checkLog(booted, "xyz #3", "throwable #3"); 109 110 // void log(java.lang.System$Logger$Level,java.util.function.Supplier) 111 LOGGER.log(Level.ERROR, () -> "xyz #4"); 112 MGR.checkLog(booted, "xyz #4"); 113 114 // void log(java.lang.System$Logger$Level,java.lang.Object) 115 LOGGER.log(Level.ERROR, new MyObject("xyz #5")); 116 MGR.checkLog(booted, "xyz #5"); 117 118 // void log(java.lang.System$Logger$Level,java.util.function.Supplier, 119 // java.lang.Throwable) 120 LOGGER.log(Level.ERROR, () -> "xyz #6", new RuntimeException("throwable #6")); 121 MGR.checkLog(booted, "xyz #6", "throwable #6"); 122 123 124 /* 125 * test logXX APIs for interface 126 * sun.util.logging.PlatformLogger.Bridge. 127 */ 128 sun.util.logging.PlatformLogger.Bridge bridge = 129 (sun.util.logging.PlatformLogger.Bridge) LOGGER; 130 131 // void log(sun.util.logging.PlatformLogger$Level,java.lang.String) 132 bridge.log(PLATFORM_LEVEL, "xyz #7"); 133 MGR.checkLog(booted, "xyz #7"); 134 135 // void log(sun.util.logging.PlatformLogger$Level,java.lang.String,java.lang.Throwable) 136 bridge.log(PLATFORM_LEVEL, "xyz #8", new RuntimeException("throwable #8")); 137 MGR.checkLog(booted, "xyz #8", "throwable #8"); 138 139 // void log(sun.util.logging.PlatformLogger$Level,java.lang.String,java.lang.Object[]) 140 bridge.log(PLATFORM_LEVEL, "xyz {0}", "#9"); 141 MGR.checkLog(booted, "xyz #9"); 142 143 // void log(sun.util.logging.PlatformLogger$Level,java.util.function.Supplier) 144 bridge.log(PLATFORM_LEVEL, () -> "xyz #10"); 145 MGR.checkLog(booted, "xyz #10"); 146 147 // void log(sun.util.logging.PlatformLogger$Level, 148 // java.lang.Throwable,java.util.function.Supplier) 149 bridge.log(PLATFORM_LEVEL, new RuntimeException("throwable #11"), () -> "xyz #11"); 150 MGR.checkLog(booted, "xyz #11", "throwable #11"); 151 152 // void logp(sun.util.logging.PlatformLogger$Level,java.lang.String, 153 // java.lang.String,java.lang.String) 154 bridge.logp(PLATFORM_LEVEL, "MyClass_#12", "MyMethod_#12", "xyz #12"); 155 MGR.checkLog(booted, "xyz #12", "MyClass_#12", "MyMethod_#12"); 156 157 // void logp(sun.util.logging.PlatformLogger$Level,java.lang.String, 158 // java.lang.String,java.util.function.Supplier) 159 bridge.logp(PLATFORM_LEVEL, "MyClass_#13", "MyMethod_#13", () -> "xyz #13"); 160 MGR.checkLog(booted, "xyz #13", "MyClass_#13", "MyMethod_#13"); 161 162 // void logp(sun.util.logging.PlatformLogger$Level,java.lang.String, 163 // java.lang.String,java.lang.String,java.lang.Object[]) 164 bridge.logp(PLATFORM_LEVEL, "MyClass_#14", "MyMethod_#14", "xyz {0}", "#14"); 165 MGR.checkLog(booted, "xyz #14", "MyClass_#14", "MyMethod_#14"); 166 167 // void logp(sun.util.logging.PlatformLogger$Level,java.lang.String, 168 // java.lang.String,java.lang.String,java.lang.Throwable) 169 bridge.logp(PLATFORM_LEVEL, "MyClass_#15", "MyMethod_#15", 170 "xyz #15", new RuntimeException("throwable #15")); 171 MGR.checkLog(booted, "xyz #15", "throwable #15", "MyClass_#15", "MyMethod_#15"); 172 173 // void logp(sun.util.logging.PlatformLogger$Level,java.lang.String, 174 // java.lang.String,java.lang.Throwable,java.util.function.Supplier) 175 bridge.logp(PLATFORM_LEVEL, "MyClass_#16", "MyMethod_#16", 176 new RuntimeException("throwable #16"), () -> "xyz #16"); 177 MGR.checkLog(booted, "xyz #16", "throwable #16", "MyClass_#16", "MyMethod_#16"); 178 179 // void logrb(sun.util.logging.PlatformLogger$Level,java.lang.String,java.lang.String, 180 // java.util.ResourceBundle,java.lang.String,java.lang.Object[]) 181 bridge.logrb(PLATFORM_LEVEL, "MyClass_#17", "MyMethod_#17", 182 BUNDLE, "abc {0}", "#17"); 183 MGR.checkLog(booted, "xyz #17", "MyClass_#17", "MyMethod_#17"); 184 185 // void logrb(sun.util.logging.PlatformLogger$Level,java.lang.String,java.lang.String, 186 // java.util.ResourceBundle,java.lang.String,java.lang.Throwable) 187 bridge.logrb(PLATFORM_LEVEL, "MyClass_#18", "MyMethod_#18", 188 BUNDLE, "abc #18", new RuntimeException("throwable #18")); 189 MGR.checkLog(booted, "xyz #18", "throwable #18", "MyClass_#18", "MyMethod_#18"); 190 191 // void logrb(sun.util.logging.PlatformLogger$Level,java.util.ResourceBundle, 192 // java.lang.String,java.lang.Object[]) 193 bridge.logrb(PLATFORM_LEVEL, BUNDLE, "abc {0}", "#19"); 194 MGR.checkLog(booted, "xyz #19"); 195 196 // void logrb(sun.util.logging.PlatformLogger$Level,java.util.ResourceBundle, 197 // java.lang.String,java.lang.Throwable) 198 bridge.logrb(PLATFORM_LEVEL, BUNDLE, "abc #20", 199 new RuntimeException("throwable #20")); 200 MGR.checkLog(booted, "xyz #20", "throwable #20"); 201 202 /* 203 * retained log content should be flushed after VM is booted. 204 */ 205 if (!booted) { 206 VM_BOOTED.getAndSet(true); 207 // trigger the flush, make sure to call LOGGER.log(...) 208 // after VM_BOOTED.getAndSet(true) and before MGR.assertCachedLog() 209 LOGGER.log(Level.ERROR, "VM was just booted! This log should flush the cached logs."); 210 MGR.assertCachedLog(); 211 } 212 } 213 } 214 215 private static class ContentManager { 216 final List<String[]> cached = new ArrayList<String[]>(); 217 String[] last; 218 219 public void cache() { 220 cached.add(last); 221 } 222 223 public ContentManager failLog(String... nonexistent) { 224 last = nonexistent; 225 for (String c : nonexistent) { 226 if (ERR.drain().contains(c)) { 227 throw new RuntimeException("Content \"" + nonexistent 228 + "\" should not exist in the log!"); 229 } 230 } 231 return this; 232 } 233 234 public void assertLog(String... logs) { 235 String log = ERR.drain(); 236 for (String str : logs) { 237 if (!log.contains(str)) { 238 throw new RuntimeException("Content \"" + str + "\" does not exist in the log!"); 239 } 240 } 241 } 242 243 public void checkLog(boolean booted, String... logs) { 244 if (!booted) { 245 failLog(logs).cache(); 246 } else { 247 assertLog(logs); 248 } 249 } 250 251 public void assertCachedLog() { 252 String log = ERR.drain(); 253 for (String[] arr : cached) { 254 for (String c : arr) { 255 if (!log.contains(c)) { 256 throw new RuntimeException("Content \"" + c + "\" does not exist in the log!"); 257 } 258 } 259 } 260 } 261 } 262 263 private static class MyObject { 264 String str; 265 266 public MyObject(String str) { 267 this.str = str; 268 } 269 270 public String toString() { 271 return str; 272 } 273 } 274 275 private static class MyResources extends ResourceBundle { 276 public Object handleGetObject(String key) { 277 if (key.contains("abc #") || key.contains("abc {")) { 278 return key.replaceAll("abc ", "xyz "); 279 } 280 return null; 281 } 282 283 public Enumeration<String> getKeys() { 284 return null; 285 } 286 } 287 }