/* * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ import java.io.PrintStream; import java.lang.System.Logger; import java.lang.System.Logger.Level; import java.util.ArrayList; import java.util.concurrent.atomic.AtomicBoolean; import java.util.Enumeration; import java.util.List; import java.util.ResourceBundle; import java.util.Set; import java.lang.reflect.Module; import jdk.internal.logger.BootstrapLogger; import jdk.internal.logger.LazyLoggers; /* * @test * @bug 8144460 8144214 * @summary Cover the logXX and LogEvent.valueOf APIs of BootstrapLogger * and logXX APIs of SimpleConsoleLogger. * @modules java.base/jdk.internal.logger:+open * java.base/sun.util.logging * @build BootstrapLoggerUtils LogStream * @run main/othervm BootstrapLoggerAPIsTest */ public class BootstrapLoggerAPIsTest { private static final LogStream ERR = new LogStream(); public static void main(String[] args) throws Exception { final ContentManager MGR = new ContentManager(); // private reflection hook that allows us to simulate a non booted VM final AtomicBoolean VM_BOOTED = new AtomicBoolean(false); BootstrapLoggerUtils.setBootedHook(() -> VM_BOOTED.get()); // We replace System.err to check the messages that have been logged // by the JUL ConsoleHandler and default SimpleConsoleLogger // implementaion System.setErr(new PrintStream(ERR)); VM_BOOTED.getAndSet(false); if (BootstrapLogger.isBooted()) { throw new RuntimeException("VM should not be booted!"); } final Logger LOGGER = LazyLoggers.getLogger("foo.bar", Thread.class.getModule()); final sun.util.logging.PlatformLogger.Level PLATFORM_LEVEL = sun.util.logging.PlatformLogger.Level.SEVERE; final MyResources BUNDLE = new MyResources(); /* * Test logXX APIs for interface java.lang.System.Logger. Log content * before VM is booted should be retained. Log content after VM was * booted should be flushed instantly. VM is not booted in first round * of loop, VM is booted in second round of loop. */ for (int i = 0; i < 2; i++) { boolean booted = BootstrapLogger.isBooted(); // make sure there is no [remaining] content in the LogStream. MGR.failLog("xyz", "throwable #", "MyClass_#", "MyMethod_#"); /* * test logXX APIs for interface java.lang.System.Logger. */ // void log(java.lang.System$Logger$Level,java.util.ResourceBundle, // java.lang.String,java.lang.Throwable) LOGGER.log(Level.ERROR, BUNDLE, "abc #0", new RuntimeException("throwable #0")); MGR.checkLog(booted, "xyz #0", "throwable #0"); // void log(java.lang.System$Logger$Level,java.util.ResourceBundle, // java.lang.String,java.lang.Object[]) LOGGER.log(Level.ERROR, BUNDLE, "abc #1"); MGR.checkLog(booted, "xyz #1"); // void log(java.lang.System$Logger$Level,java.lang.String,java.lang.Object[]) LOGGER.log(Level.ERROR, BUNDLE, "abc {0}", "#2"); MGR.checkLog(booted, "xyz #2"); // void log(java.lang.System$Logger$Level,java.lang.String,java.lang.Throwable) LOGGER.log(Level.ERROR, "xyz #3", new RuntimeException("throwable #3")); MGR.checkLog(booted, "xyz #3", "throwable #3"); // void log(java.lang.System$Logger$Level,java.util.function.Supplier) LOGGER.log(Level.ERROR, () -> "xyz #4"); MGR.checkLog(booted, "xyz #4"); // void log(java.lang.System$Logger$Level,java.lang.Object) LOGGER.log(Level.ERROR, new MyObject("xyz #5")); MGR.checkLog(booted, "xyz #5"); // void log(java.lang.System$Logger$Level,java.util.function.Supplier, // java.lang.Throwable) LOGGER.log(Level.ERROR, () -> "xyz #6", new RuntimeException("throwable #6")); MGR.checkLog(booted, "xyz #6", "throwable #6"); /* * test logXX APIs for interface * sun.util.logging.PlatformLogger.Bridge. */ sun.util.logging.PlatformLogger.Bridge bridge = (sun.util.logging.PlatformLogger.Bridge) LOGGER; // void log(sun.util.logging.PlatformLogger$Level,java.lang.String) bridge.log(PLATFORM_LEVEL, "xyz #7"); MGR.checkLog(booted, "xyz #7"); // void log(sun.util.logging.PlatformLogger$Level,java.lang.String,java.lang.Throwable) bridge.log(PLATFORM_LEVEL, "xyz #8", new RuntimeException("throwable #8")); MGR.checkLog(booted, "xyz #8", "throwable #8"); // void log(sun.util.logging.PlatformLogger$Level,java.lang.String,java.lang.Object[]) bridge.log(PLATFORM_LEVEL, "xyz {0}", "#9"); MGR.checkLog(booted, "xyz #9"); // void log(sun.util.logging.PlatformLogger$Level,java.util.function.Supplier) bridge.log(PLATFORM_LEVEL, () -> "xyz #10"); MGR.checkLog(booted, "xyz #10"); // void log(sun.util.logging.PlatformLogger$Level, // java.lang.Throwable,java.util.function.Supplier) bridge.log(PLATFORM_LEVEL, new RuntimeException("throwable #11"), () -> "xyz #11"); MGR.checkLog(booted, "xyz #11", "throwable #11"); // void logp(sun.util.logging.PlatformLogger$Level,java.lang.String, // java.lang.String,java.lang.String) bridge.logp(PLATFORM_LEVEL, "MyClass_#12", "MyMethod_#12", "xyz #12"); MGR.checkLog(booted, "xyz #12", "MyClass_#12", "MyMethod_#12"); // void logp(sun.util.logging.PlatformLogger$Level,java.lang.String, // java.lang.String,java.util.function.Supplier) bridge.logp(PLATFORM_LEVEL, "MyClass_#13", "MyMethod_#13", () -> "xyz #13"); MGR.checkLog(booted, "xyz #13", "MyClass_#13", "MyMethod_#13"); // void logp(sun.util.logging.PlatformLogger$Level,java.lang.String, // java.lang.String,java.lang.String,java.lang.Object[]) bridge.logp(PLATFORM_LEVEL, "MyClass_#14", "MyMethod_#14", "xyz {0}", "#14"); MGR.checkLog(booted, "xyz #14", "MyClass_#14", "MyMethod_#14"); // void logp(sun.util.logging.PlatformLogger$Level,java.lang.String, // java.lang.String,java.lang.String,java.lang.Throwable) bridge.logp(PLATFORM_LEVEL, "MyClass_#15", "MyMethod_#15", "xyz #15", new RuntimeException("throwable #15")); MGR.checkLog(booted, "xyz #15", "throwable #15", "MyClass_#15", "MyMethod_#15"); // void logp(sun.util.logging.PlatformLogger$Level,java.lang.String, // java.lang.String,java.lang.Throwable,java.util.function.Supplier) bridge.logp(PLATFORM_LEVEL, "MyClass_#16", "MyMethod_#16", new RuntimeException("throwable #16"), () -> "xyz #16"); MGR.checkLog(booted, "xyz #16", "throwable #16", "MyClass_#16", "MyMethod_#16"); // void logrb(sun.util.logging.PlatformLogger$Level,java.lang.String,java.lang.String, // java.util.ResourceBundle,java.lang.String,java.lang.Object[]) bridge.logrb(PLATFORM_LEVEL, "MyClass_#17", "MyMethod_#17", BUNDLE, "abc {0}", "#17"); MGR.checkLog(booted, "xyz #17", "MyClass_#17", "MyMethod_#17"); // void logrb(sun.util.logging.PlatformLogger$Level,java.lang.String,java.lang.String, // java.util.ResourceBundle,java.lang.String,java.lang.Throwable) bridge.logrb(PLATFORM_LEVEL, "MyClass_#18", "MyMethod_#18", BUNDLE, "abc #18", new RuntimeException("throwable #18")); MGR.checkLog(booted, "xyz #18", "throwable #18", "MyClass_#18", "MyMethod_#18"); // void logrb(sun.util.logging.PlatformLogger$Level,java.util.ResourceBundle, // java.lang.String,java.lang.Object[]) bridge.logrb(PLATFORM_LEVEL, BUNDLE, "abc {0}", "#19"); MGR.checkLog(booted, "xyz #19"); // void logrb(sun.util.logging.PlatformLogger$Level,java.util.ResourceBundle, // java.lang.String,java.lang.Throwable) bridge.logrb(PLATFORM_LEVEL, BUNDLE, "abc #20", new RuntimeException("throwable #20")); MGR.checkLog(booted, "xyz #20", "throwable #20"); /* * retained log content should be flushed after VM is booted. */ if (!booted) { VM_BOOTED.getAndSet(true); // trigger the flush, make sure to call LOGGER.log(...) // after VM_BOOTED.getAndSet(true) and before MGR.assertCachedLog() LOGGER.log(Level.ERROR, "VM was just booted! This log should flush the cached logs."); MGR.assertCachedLog(); } } } private static class ContentManager { final List<String[]> cached = new ArrayList<String[]>(); String[] last; public void cache() { cached.add(last); } public ContentManager failLog(String... nonexistent) { last = nonexistent; for (String c : nonexistent) { if (ERR.drain().contains(c)) { throw new RuntimeException("Content \"" + nonexistent + "\" should not exist in the log!"); } } return this; } public void assertLog(String... logs) { String log = ERR.drain(); for (String str : logs) { if (!log.contains(str)) { throw new RuntimeException("Content \"" + str + "\" does not exist in the log!"); } } } public void checkLog(boolean booted, String... logs) { if (!booted) { failLog(logs).cache(); } else { assertLog(logs); } } public void assertCachedLog() { String log = ERR.drain(); for (String[] arr : cached) { for (String c : arr) { if (!log.contains(c)) { throw new RuntimeException("Content \"" + c + "\" does not exist in the log!"); } } } } } private static class MyObject { String str; public MyObject(String str) { this.str = str; } public String toString() { return str; } } private static class MyResources extends ResourceBundle { public Object handleGetObject(String key) { if (key.contains("abc #") || key.contains("abc {")) { return key.replaceAll("abc ", "xyz "); } return null; } public Enumeration<String> getKeys() { return null; } } }