gt:                 Logger logger5 = manager.getLogger("");
context: /*
   * Copyright (c) 2013, 2016, 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.security.CodeSource;
  import java.security.Permission;
  import java.security.PermissionCollection;
  import java.security.Permissions;
  import java.security.Policy;
  import java.security.ProtectionDomain;
  import java.util.EnumSet;
  import java.util.HashMap;
  import java.util.Map;
  import java.util.logging.LogManager;
  import java.util.logging.Logger;
  import java.util.logging.LoggingPermission;
  import jdk.internal.misc.JavaAWTAccess;
  import jdk.internal.misc.SharedSecrets;
  
  /*
   * @test
   * @bug 8017174 8010727 8019945
   * @summary  NPE when using Logger.getAnonymousLogger or
   *           LogManager.getLogManager().getLogger
   *
   * @modules java.base/jdk.internal.misc
   *          java.logging
   * @run main/othervm -Dtest.security=off TestAppletLoggerContext LoadingApplet
   * @run main/othervm -Dtest.security=on TestAppletLoggerContext  LoadingApplet
   * @run main/othervm -Dtest.security=off TestAppletLoggerContext LoadingMain
   * @run main/othervm -Dtest.security=on TestAppletLoggerContext  LoadingMain
   * @run main/othervm -Dtest.security=off TestAppletLoggerContext One
   * @run main/othervm -Dtest.security=on TestAppletLoggerContext  One
   * @run main/othervm -Dtest.security=off TestAppletLoggerContext Two
   * @run main/othervm -Dtest.security=on TestAppletLoggerContext  Two
   * @run main/othervm -Dtest.security=off TestAppletLoggerContext Three
   * @run main/othervm -Dtest.security=on TestAppletLoggerContext  Three
   * @run main/othervm -Dtest.security=off TestAppletLoggerContext Four
   * @run main/othervm -Dtest.security=on TestAppletLoggerContext  Four
   * @run main/othervm -Dtest.security=off TestAppletLoggerContext Five
   * @run main/othervm -Dtest.security=on TestAppletLoggerContext  Five
   * @run main/othervm -Dtest.security=off TestAppletLoggerContext Six
   * @run main/othervm -Dtest.security=on TestAppletLoggerContext  Six
   * @run main/othervm -Dtest.security=off TestAppletLoggerContext Seven
   * @run main/othervm -Dtest.security=on TestAppletLoggerContext  Seven
   * @run main/othervm -Dtest.security=off TestAppletLoggerContext
   * @run main/othervm -Dtest.security=on TestAppletLoggerContext
   */
  
  // NOTE: We run in other VM in order to 1. switch security manager and 2. cause
  // LogManager class to be loaded anew.
  public class TestAppletLoggerContext {
  
      // Avoids the hassle of dealing with files and system props...
      static class SimplePolicy extends Policy {
          private final Permissions perms;
          public SimplePolicy(Permission... permissions) {
              perms = new Permissions();
              for (Permission permission : permissions) {
                  perms.add(permission);
              }
          }
          @Override
          public PermissionCollection getPermissions(CodeSource cs) {
              return perms;
          }
          @Override
          public PermissionCollection getPermissions(ProtectionDomain pd) {
              return perms;
          }
          @Override
          public boolean implies(ProtectionDomain pd, Permission p) {
             return perms.implies(p);
          }
      }
  
      // The bridge class initializes the logging system.
      // It stubs the applet context in order to simulate context changes.
      //
      public static class Bridge {
  
          private static class JavaAWTAccessStub implements JavaAWTAccess {
              boolean active = true;
  
              private static class TestExc {
                  private final Map<Object, Object> map = new HashMap<>();
                  void put(Object key, Object v) { map.put(key, v); }
                  Object get(Object key) { return map.get(key); }
                  void remove(Object o) { map.remove(o); }
                  public static TestExc exc(Object o) {
                      return TestExc.class.cast(o);
                  }
              }
  
              TestExc exc;
  
              @Override
              public Object getAppletContext() { return active ? exc : null; }
          }
  
          static final JavaAWTAccessStub javaAwtAccess = new JavaAWTAccessStub();
          public static void init() {
              SharedSecrets.setJavaAWTAccess(javaAwtAccess);
              if (System.getProperty("test.security", "on").equals("on")) {
                  Policy p = new SimplePolicy(new LoggingPermission("control", null),
                      new RuntimePermission("setContextClassLoader"),
                      new RuntimePermission("shutdownHooks"));
                  Policy.setPolicy(p);
                  System.setSecurityManager(new SecurityManager());
              }
          }
  
          public static void changeContext() {
              System.out.println("... Switching to a new applet context ...");
              javaAwtAccess.active = true;
              javaAwtAccess.exc = new JavaAWTAccessStub.TestExc();
          }
  
          public static void desactivate() {
              System.out.println("... Running with no applet context ...");
              javaAwtAccess.exc = null;
              javaAwtAccess.active = false;
          }
  
          public static class CustomAnonymousLogger extends Logger {
              public CustomAnonymousLogger() {
                  this("");
              }
              public CustomAnonymousLogger(String name) {
                  super(null, null);
                  System.out.println( " LogManager: " +LogManager.getLogManager());
                  System.out.println( " getLogger: " +LogManager.getLogManager().getLogger(name));
                  setParent(LogManager.getLogManager().getLogger(name));
              }
          }
  
          public static class CustomLogger extends Logger {
              CustomLogger(String name) {
                  super(name, null);
              }
          }
      }
  
      public static enum TestCase {
          LoadingApplet, LoadingMain, One, Two, Three, Four, Five, Six, Seven;
          public void test() {
              switch(this) {
                  // When run - each of these two tests must be
                  // run before any other tests and before each other.
                  case LoadingApplet: testLoadingApplet(); break;
                  case LoadingMain:   testLoadingMain(); break;
                  case One:   testOne(); break;
                  case Two:   testTwo(); break;
                  case Three: testThree(); break;
                  case Four:  testFour(); break;
                  case Five:  testFive(); break;
                  case Six:   testSix(); break;
                  case Seven: testSeven(); break;
              }
          }
          public String describe() {
              switch(this) {
                  case LoadingApplet:
                      return "Test that when the LogManager class is"
                          + " loaded in  an applet thread first,"
                          + "\n all LoggerContexts are correctly initialized";
                  case LoadingMain:
                      return "Test that when the LogManager class is"
                          + " loaded in  the main thread first,"
                          + "\n all LoggerContexts are correctly initialized";
                  case One:
                      return "Test that Logger.getAnonymousLogger()"
                          + " and new CustomAnonymousLogger() don't throw NPE";
                  case Two:
                      return "Test that Logger.getLogger(\"\")"
                              + " does not return null nor throws NPE";
                  case Three:
                      return "Test that LogManager.getLogManager().getLogger(\"\")"
                              + " does not return null nor throws NPE";
                  case Four:
                      return "Test that Logger.getLogger(Logger.GLOBAL_LOGGER_NAME)"
                              + " does not return null,\n and that"
                              + " new CustomAnonymousLogger(Logger.GLOBAL_LOGGER_NAME)"
                              + " does not throw NPE";
                  case Five:
                      return "Test that LogManager.getLogManager().getLogger(Logger.GLOBAL_LOGGER_NAME)"
                              + "\n does not return null nor throws NPE";
                  case Six:
                      return "Test that manager.getLogger(Logger.GLOBAL_LOGGER_NAME)"
                              + " returns null\n when manager is not the default"
                              + " LogManager instance.\n"
                              + "Test adding a new logger named \"global\" in that"
                              + " non default instance.";
                  case Seven: return "Test that manager.getLogger(\"\")"
                              + " returns null\n when manager is not the default"
                              + " LogManager instance.\n"
                              + "Test adding a new logger named \"\" in that"
                              + " non default instance.";
                  default: return "Undefined";
              }
          }
      };
  
      /**
       * @param args the command line arguments
       */
      public static void main(String[] args) {
          Bridge.init();
          EnumSet<TestCase> tests = EnumSet.noneOf(TestCase.class);
          for (String arg : args) {
              tests.add(TestCase.valueOf(arg));
          }
          if (args.length == 0) {
              tests = EnumSet.complementOf(EnumSet.of(TestCase.LoadingMain));
          }
          final EnumSet<TestCase> loadingTests =
              EnumSet.of(TestCase.LoadingApplet, TestCase.LoadingMain);
          int testrun = 0;
          for (TestCase test : tests) {
              if (loadingTests.contains(test)) {
                  if (testrun > 0) {
                      throw new UnsupportedOperationException("Test case "
                            + test + " must be executed first!");
                  }
              }
              System.out.println("Testing "+ test+": ");
              System.out.println(test.describe());
              try {
                  test.test();
              } catch (Exception x) {
                 throw new Error(String.valueOf(test)
                     + (System.getSecurityManager() == null ? " without " : " with ")
                     + "security failed: "+x+"\n "+"FAILED: "+test.describe()+"\n", x);
              } finally {
                  testrun++;
              }
              Bridge.changeContext();
              System.out.println("PASSED: "+ test);
          }
      }
  
      public static void testLoadingApplet() {
          Bridge.changeContext();
  
          Logger bar = new Bridge.CustomLogger("com.foo.Bar");
          LogManager.getLogManager().addLogger(bar);
          assertNotNull(bar.getParent());
          testParent(bar);
          testParent(LogManager.getLogManager().getLogger("global"));
          testParent(LogManager.getLogManager().getLogger(bar.getName()));
  
          Bridge.desactivate();
  
          Logger foo = new Bridge.CustomLogger("com.foo.Foo");
          boolean b = LogManager.getLogManager().addLogger(foo);
          assertEquals(Boolean.TRUE, Boolean.valueOf(b));
          assertNotNull(foo.getParent());
          testParent(foo);
          testParent(LogManager.getLogManager().getLogger("global"));
          testParent(LogManager.getLogManager().getLogger(foo.getName()));
      }
  
      public static void testLoadingMain() {
          Bridge.desactivate();
  
          Logger bar = new Bridge.CustomLogger("com.foo.Bar");
          LogManager.getLogManager().addLogger(bar);
          assertNotNull(bar.getParent());
          testParent(bar);
          testParent(LogManager.getLogManager().getLogger("global"));
          testParent(LogManager.getLogManager().getLogger(bar.getName()));
  
          Bridge.changeContext();
  
          Logger foo = new Bridge.CustomLogger("com.foo.Foo");
          boolean b = LogManager.getLogManager().addLogger(foo);
          assertEquals(Boolean.TRUE, Boolean.valueOf(b));
          assertNotNull(foo.getParent());
          testParent(foo);
          testParent(LogManager.getLogManager().getLogger("global"));
          testParent(LogManager.getLogManager().getLogger(foo.getName()));
  
      }
  
      public static void testOne() {
          for (int i=0; i<3 ; i++) {
              Logger logger1 = Logger.getAnonymousLogger();
              Logger logger1b = Logger.getAnonymousLogger();
              Bridge.changeContext();
              Logger logger2 = Logger.getAnonymousLogger();
              Logger logger2b = Logger.getAnonymousLogger();
              Bridge.changeContext();
              Logger logger3 = new Bridge.CustomAnonymousLogger();
              Logger logger3b = new Bridge.CustomAnonymousLogger();
              Bridge.changeContext();
              Logger logger4 = new Bridge.CustomAnonymousLogger();
              Logger logger4b = new Bridge.CustomAnonymousLogger();
          }
      }
  
  
      public static void testTwo() {
          for (int i=0; i<3 ; i++) {
              Logger logger1 = Logger.getLogger("");
              Logger logger1b = Logger.getLogger("");
              assertNotNull(logger1);
              assertNotNull(logger1b);
              assertEquals(logger1, logger1b);
              Bridge.changeContext();
              Logger logger2 = Logger.getLogger("");
              Logger logger2b = Logger.getLogger("");
              assertNotNull(logger2);
              assertNotNull(logger2b);
              assertEquals(logger2, logger2b);
              assertEquals(logger1, logger2);
          }
      }
  
      public static void testThree() {
          for (int i=0; i<3 ; i++) {
              Logger logger1 = LogManager.getLogManager().getLogger("");
              Logger logger1b = LogManager.getLogManager().getLogger("");
              assertNotNull(logger1);
              assertNotNull(logger1b);
              assertEquals(logger1, logger1b);
              Bridge.changeContext();
              Logger logger2 = LogManager.getLogManager().getLogger("");
              Logger logger2b = LogManager.getLogManager().getLogger("");
              assertNotNull(logger2);
              assertNotNull(logger2b);
              assertEquals(logger2, logger2b);
              assertEquals(logger1, logger2);
          }
      }
  
      public static void testFour() {
          for (int i=0; i<3 ; i++) {
              Logger logger1 = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
              Logger logger1b = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
              assertNotNull(logger1);
              assertNotNull(logger1b);
              assertEquals(logger1, logger1b);
              Bridge.changeContext();
  
              Logger logger2 = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
              Logger logger2b = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
              assertNotNull(logger2);
              assertNotNull(logger2b);
              assertEquals(logger2, logger2b);
  
              assertEquals(logger1, logger2);
  
              Bridge.changeContext();
              Logger logger3 = new Bridge.CustomAnonymousLogger(Logger.GLOBAL_LOGGER_NAME);
              Logger logger3b = new Bridge.CustomAnonymousLogger(Logger.GLOBAL_LOGGER_NAME);
              Bridge.changeContext();
              Logger logger4 = new Bridge.CustomAnonymousLogger(Logger.GLOBAL_LOGGER_NAME);
              Logger logger4b = new Bridge.CustomAnonymousLogger(Logger.GLOBAL_LOGGER_NAME);
          }
      }
  
      public static void testFive() {
          for (int i=0; i<3 ; i++) {
              Logger logger1 = LogManager.getLogManager().getLogger(Logger.GLOBAL_LOGGER_NAME);
              Logger logger1b = LogManager.getLogManager().getLogger(Logger.GLOBAL_LOGGER_NAME);
              assertNotNull(logger1);
              assertNotNull(logger1b);
              assertEquals(logger1, logger1b);
  
              Bridge.changeContext();
  
              Logger logger2 = LogManager.getLogManager().getLogger(Logger.GLOBAL_LOGGER_NAME);
              Logger logger2b = LogManager.getLogManager().getLogger(Logger.GLOBAL_LOGGER_NAME);
              assertNotNull(logger2);
              assertNotNull(logger2b);
              assertEquals(logger2, logger2b);
  
              assertEquals(logger1, logger2);
          }
      }
  
      /**
       * This test is designed to test the behavior of additional LogManager instances.
       * It must be noted that if the security manager is off, then calling
       * Bridge.changeContext() has actually no effect - which explains why we have
       * some differences between the cases security manager on & security manager
       * off.
       **/
      public static void testSix() {
          for (int i=0; i<3 ; i++) {
              Bridge.desactivate();
              LogManager manager = new LogManager() {};
              Logger logger1 = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
              Logger logger1b = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
              assertNull(logger1);
              assertNull(logger1b);
              Logger global = new Bridge.CustomLogger(Logger.GLOBAL_LOGGER_NAME);
              manager.addLogger(global);
              Logger logger2 = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
              Logger logger2b = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
              assertNotNull(logger2);
              assertNotNull(logger2b);
              assertEquals(logger2, global);
              assertEquals(logger2b, global);
              assertNull(manager.getLogger(""));
              assertNull(manager.getLogger(""));
  
              for (int j = 0; j<3; j++) {
                  Bridge.changeContext();
  
                  // this is not a supported configuration:
                  // We are in an applet context with several log managers.
                  // We however need to check our assumptions...
  
                  // Applet context => root logger and global logger should also be null.
  
                  Logger expected = (System.getSecurityManager() == null ? global : null);
                  Logger logger3 = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
                  Logger logger3b = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
                  assertEquals(expected, logger3);
                  assertEquals(expected, logger3b);
                  Logger global2 = new Bridge.CustomLogger(Logger.GLOBAL_LOGGER_NAME);
                  manager.addLogger(global2);
                  Logger logger4 = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
                  Logger logger4b = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
                  assertNotNull(logger4);
                  assertNotNull(logger4b);
                  expected = (System.getSecurityManager() == null ? global : global2);;
                  assertEquals(logger4,  expected);
                  assertEquals(logger4b, expected);
  
  