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