8144460: Improve the code coverage for BootstrapLogger and SimpleConsoleLogger APIs and verify bug fix JDK-8144214
authormli
Wed, 02 Dec 2015 19:46:46 -0800
changeset 34428 39f1caf048c3
parent 34427 38c26b9b411c
child 34429 8893c723602e
8144460: Improve the code coverage for BootstrapLogger and SimpleConsoleLogger APIs and verify bug fix JDK-8144214 Summary: Cover the logXX and LogEvent.valueOf APIs of BootstrapLogger and logXX APIs of SimpleConsoleLogger Reviewed-by: dfuchs
jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerAPIsTest.java
jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerTest.java
jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerUtils.java
jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/LogStream.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerAPIsTest.java	Wed Dec 02 19:46:46 2015 -0800
@@ -0,0 +1,286 @@
+/*
+ * 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 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
+ * @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);
+        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;
+        }
+    }
+}
--- a/jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerTest.java	Wed Dec 02 19:27:16 2015 -0800
+++ b/jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerTest.java	Wed Dec 02 19:46:46 2015 -0800
@@ -21,19 +21,14 @@
  * questions.
  */
 
-import java.io.ByteArrayOutputStream;
-import java.io.OutputStream;
 import java.io.PrintStream;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
 import java.lang.reflect.Array;
 import java.lang.reflect.Field;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.function.BooleanSupplier;
+import java.lang.reflect.Method;
 import java.lang.System.Logger;
 import java.lang.System.Logger.Level;
-import java.lang.ref.ReferenceQueue;
-import java.lang.ref.WeakReference;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
 import java.security.AllPermission;
 import java.security.CodeSource;
 import java.security.Permission;
@@ -41,6 +36,7 @@
 import java.security.Permissions;
 import java.security.Policy;
 import java.security.ProtectionDomain;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.Optional;
 import java.util.Set;
 import java.util.stream.Collectors;
@@ -56,25 +52,17 @@
             Tests the behavior of bootstrap loggers (and SimpleConsoleLoggers
  *          too).
  * @modules java.base/jdk.internal.logger
+ * @build BootstrapLoggerUtils LogStream
  * @run main/othervm BootstrapLoggerTest NO_SECURITY
  * @run main/othervm BootstrapLoggerTest SECURE
  * @run main/othervm/timeout=120 BootstrapLoggerTest SECURE_AND_WAIT
  */
 public class BootstrapLoggerTest {
 
-    static final Method awaitPending;
     static final Method isAlive;
-    static final Field isBooted;
     static final Field logManagerInitialized;
     static {
         try {
-            isBooted = BootstrapLogger.class.getDeclaredField("isBooted");
-            isBooted.setAccessible(true);
-            // private reflection hook that allows us to test wait until all
-            // the tasks pending in the BootstrapExecutor are finished.
-            awaitPending = BootstrapLogger.class
-                    .getDeclaredMethod("awaitPendingTasks");
-            awaitPending.setAccessible(true);
             // private reflection hook that allows us to test whether
             // the BootstrapExecutor is alive.
             isAlive = BootstrapLogger.class
@@ -90,43 +78,6 @@
         }
     }
 
-    static void awaitPending() {
-        try {
-            awaitPending.invoke(null);
-        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
-            ex.printStackTrace(LogStream.err);
-        }
-    }
-
-    /**
-     * We use an instance of this class to check what the logging system has
-     * printed on System.err.
-     */
-    public static class LogStream extends OutputStream {
-
-        final static PrintStream err = System.err;
-        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
-
-        public LogStream() {
-            super();
-        }
-
-        @Override
-        public synchronized void write(int b) {
-            baos.write(b);
-            err.write(b);
-        }
-
-        public String drain() {
-            awaitPending();
-            synchronized(this) {
-                String txt = baos.toString();
-                baos.reset();
-                return txt;
-            }
-        }
-    }
-
     static enum TestCase {
         NO_SECURITY, SECURE, SECURE_AND_WAIT
     }
@@ -142,7 +93,7 @@
 
         // private reflection hook that allows us to simulate a non booted VM
         final AtomicBoolean vmBooted = new AtomicBoolean(false);
-        isBooted.set(null,(BooleanSupplier) () -> vmBooted.get());
+        BootstrapLoggerUtils.setBootedHook(() -> vmBooted.get());
 
         // We  replace System.err to check the messages that have been logged
         // by the JUL ConsoleHandler and default SimpleConsoleLogger
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerUtils.java	Wed Dec 02 19:46:46 2015 -0800
@@ -0,0 +1,61 @@
+/*
+ * 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.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.function.BooleanSupplier;
+
+import jdk.internal.logger.BootstrapLogger;
+
+class BootstrapLoggerUtils {
+
+    private static final Field IS_BOOTED;
+    private static final Method AWAIT_PENDING;
+
+    static {
+        try {
+            IS_BOOTED = BootstrapLogger.class.getDeclaredField("isBooted");
+            IS_BOOTED.setAccessible(true);
+            // private reflection hook that allows us to test wait until all
+            // the tasks pending in the BootstrapExecutor are finished.
+            AWAIT_PENDING = BootstrapLogger.class.getDeclaredMethod("awaitPendingTasks");
+            AWAIT_PENDING.setAccessible(true);
+        } catch (Exception ex) {
+            throw new ExceptionInInitializerError(ex);
+        }
+    }
+
+    static void setBootedHook(BooleanSupplier supplier) throws IllegalAccessException {
+        IS_BOOTED.set(null, supplier);
+    }
+
+    static void awaitPending() {
+        try {
+            AWAIT_PENDING.invoke(null);
+        } catch (IllegalAccessException | IllegalArgumentException
+                | InvocationTargetException ex) {
+            ex.printStackTrace();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/LogStream.java	Wed Dec 02 19:46:46 2015 -0800
@@ -0,0 +1,58 @@
+/*
+ * 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.ByteArrayOutputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+
+import jdk.internal.logger.BootstrapLogger;
+
+/**
+ * We use an instance of this class to check what the logging system has printed
+ * on System.err.
+ */
+class LogStream extends OutputStream {
+
+    static final PrintStream err = System.err;
+
+    private final ByteArrayOutputStream BAOS = new ByteArrayOutputStream();
+
+    LogStream() {
+        super();
+    }
+
+    @Override
+    public synchronized void write(int b) {
+        BAOS.write(b);
+        err.write(b);
+    }
+
+    String drain() {
+        BootstrapLoggerUtils.awaitPending();
+        synchronized (this) {
+            String txt = BAOS.toString();
+            BAOS.reset();
+            return txt;
+        }
+    }
+}