1 /*
   2  * Copyright (c) 2013, 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.security.CodeSource;
  25 import java.security.Permission;
  26 import java.security.PermissionCollection;
  27 import java.security.Permissions;
  28 import java.security.Policy;
  29 import java.security.ProtectionDomain;
  30 import java.util.EnumSet;
  31 import java.util.HashMap;
  32 import java.util.Map;
  33 import java.util.logging.LogManager;
  34 import java.util.logging.Logger;
  35 import java.util.logging.LoggingPermission;
  36 import sun.misc.JavaAWTAccess;
  37 import sun.misc.SharedSecrets;
  38 
  39 /*
  40  * @test
  41  * @bug 8017174 8010727
  42  * @summary  NPE when using Logger.getAnonymousLogger or
  43  *           LogManager.getLogManager().getLogger
  44  *
  45  * @run main/othervm -Dtest.security=off TestAppletLoggerContext LoadingApplet
  46  * @run main/othervm -Dtest.security=on TestAppletLoggerContext  LoadingApplet
  47  * @run main/othervm -Dtest.security=off TestAppletLoggerContext LoadingMain
  48  * @run main/othervm -Dtest.security=on TestAppletLoggerContext  LoadingMain
  49  * @run main/othervm -Dtest.security=off TestAppletLoggerContext One
  50  * @run main/othervm -Dtest.security=on TestAppletLoggerContext  One
  51  * @run main/othervm -Dtest.security=off TestAppletLoggerContext Two
  52  * @run main/othervm -Dtest.security=on TestAppletLoggerContext  Two
  53  * @run main/othervm -Dtest.security=off TestAppletLoggerContext Three
  54  * @run main/othervm -Dtest.security=on TestAppletLoggerContext  Three
  55  * @run main/othervm -Dtest.security=off TestAppletLoggerContext Four
  56  * @run main/othervm -Dtest.security=on TestAppletLoggerContext  Four
  57  * @run main/othervm -Dtest.security=off TestAppletLoggerContext Five
  58  * @run main/othervm -Dtest.security=on TestAppletLoggerContext  Five
  59  * @run main/othervm -Dtest.security=off TestAppletLoggerContext Six
  60  * @run main/othervm -Dtest.security=on TestAppletLoggerContext  Six
  61  * @run main/othervm -Dtest.security=off TestAppletLoggerContext Seven
  62  * @run main/othervm -Dtest.security=on TestAppletLoggerContext  Seven
  63  * @run main/othervm -Dtest.security=off TestAppletLoggerContext
  64  * @run main/othervm -Dtest.security=on TestAppletLoggerContext
  65  */
  66 
  67 // NOTE: We run in other VM in order to 1. switch security manager and 2. cause
  68 // LogManager class to be loaded anew.
  69 public class TestAppletLoggerContext {
  70 
  71     // Avoids the hassle of dealing with files and system props...
  72     static class SimplePolicy extends Policy {
  73         private final Permissions perms;
  74         public SimplePolicy(Permission... permissions) {
  75             perms = new Permissions();
  76             for (Permission permission : permissions) {
  77                 perms.add(permission);
  78             }
  79         }
  80         @Override
  81         public PermissionCollection getPermissions(CodeSource cs) {
  82             return perms;
  83         }
  84         @Override
  85         public PermissionCollection getPermissions(ProtectionDomain pd) {
  86             return perms;
  87         }
  88         @Override
  89         public boolean implies(ProtectionDomain pd, Permission p) {
  90            return perms.implies(p);
  91         }
  92     }
  93 
  94     // The bridge class initializes the logging system.
  95     // It stubs the applet context in order to simulate context changes.
  96     //
  97     public static class Bridge {
  98 
  99         private static class JavaAWTAccessStub implements JavaAWTAccess {
 100             boolean active = true;
 101 
 102             private static class TestExc {
 103                 private final Map<Object, Object> map = new HashMap<>();
 104                 void put(Object key, Object v) { map.put(key, v); }
 105                 Object get(Object key) { return map.get(key); }
 106                 void remove(Object o) { map.remove(o); }
 107                 public static TestExc exc(Object o) {
 108                     return TestExc.class.cast(o);
 109                 }
 110             }
 111 
 112             TestExc exc;
 113 
 114             @Override
 115             public Object getAppletContext() { return active ? exc : null; }
 116             @Override
 117             public Object get(Object o) { return exc.get(o); }
 118             @Override
 119             public void put(Object o, Object o1) { exc.put(o, o1); }
 120             @Override
 121             public void remove(Object o) { exc.remove(o); }
 122             @Override
 123             public boolean isDisposed() { return false; }
 124             @Override
 125             public boolean isMainAppContext() { return !active || exc == null; }
 126         }
 127 
 128         final static JavaAWTAccessStub javaAwtAccess = new JavaAWTAccessStub();
 129         public static void init() {
 130             SharedSecrets.setJavaAWTAccess(javaAwtAccess);
 131             if (System.getProperty("test.security", "on").equals("on")) {
 132                 Policy p = new SimplePolicy(new LoggingPermission("control", null),
 133                     new RuntimePermission("setContextClassLoader"),
 134                     new RuntimePermission("shutdownHooks"));
 135                 Policy.setPolicy(p);
 136                 System.setSecurityManager(new SecurityManager());
 137             }
 138         }
 139 
 140         public static void changeContext() {
 141             System.out.println("... Switching to a new applet context ...");
 142             javaAwtAccess.active = true;
 143             javaAwtAccess.exc = new JavaAWTAccessStub.TestExc();
 144         }
 145 
 146         public static void desactivate() {
 147             System.out.println("... Running with no applet context ...");
 148             javaAwtAccess.exc = null;
 149             javaAwtAccess.active = false;
 150         }
 151 
 152         public static class CustomAnonymousLogger extends Logger {
 153             public CustomAnonymousLogger() {
 154                 this("");
 155             }
 156             public CustomAnonymousLogger(String name) {
 157                 super(null, null);
 158                 System.out.println( " LogManager: " +LogManager.getLogManager());
 159                 System.out.println( " getLogger: " +LogManager.getLogManager().getLogger(name));
 160                 setParent(LogManager.getLogManager().getLogger(name));
 161             }
 162         }
 163 
 164         public static class CustomLogger extends Logger {
 165             CustomLogger(String name) {
 166                 super(name, null);
 167             }
 168         }
 169     }
 170 
 171     public static enum TestCase {
 172         LoadingApplet, LoadingMain, One, Two, Three, Four, Five, Six, Seven;
 173         public void test() {
 174             switch(this) {
 175                 // When run - each of these two tests must be
 176                 // run before any other tests and before each other.
 177                 case LoadingApplet: testLoadingApplet(); break;
 178                 case LoadingMain:   testLoadingMain(); break;
 179                 case One:   testOne(); break;
 180                 case Two:   testTwo(); break;
 181                 case Three: testThree(); break;
 182                 case Four:  testFour(); break;
 183                 case Five:  testFive(); break;
 184                 case Six:   testSix(); break;
 185                 case Seven: testSeven(); break;
 186             }
 187         }
 188         public String describe() {
 189             switch(this) {
 190                 case LoadingApplet:
 191                     return "Test that when the LogManager class is"
 192                         + " loaded in  an applet thread first,"
 193                         + "\n all LoggerContexts are correctly initialized";
 194                 case LoadingMain:
 195                     return "Test that when the LogManager class is"
 196                         + " loaded in  the main thread first,"
 197                         + "\n all LoggerContexts are correctly initialized";
 198                 case One:
 199                     return "Test that Logger.getAnonymousLogger()"
 200                         + " and new CustomAnonymousLogger() don't throw NPE";
 201                 case Two:
 202                     return "Test that Logger.getLogger(\"\")"
 203                             + " does not return null nor throws NPE";
 204                 case Three:
 205                     return "Test that LogManager.getLogManager().getLogger(\"\")"
 206                             + " does not return null nor throws NPE";
 207                 case Four:
 208                     return "Test that Logger.getLogger(Logger.GLOBAL_LOGGER_NAME)"
 209                             + " does not return null,\n and that"
 210                             + " new CustomAnonymousLogger(Logger.GLOBAL_LOGGER_NAME)"
 211                             + " does not throw NPE";
 212                 case Five:
 213                     return "Test that LogManager.getLogManager().getLogger(Logger.GLOBAL_LOGGER_NAME)"
 214                             + "\n does not return null nor throws NPE";
 215                 case Six:
 216                     return "Test that manager.getLogger(Logger.GLOBAL_LOGGER_NAME)"
 217                             + " returns null\n when manager is not the default"
 218                             + " LogManager instance.\n"
 219                             + "Test adding a new logger named \"global\" in that"
 220                             + " non default instance.";
 221                 case Seven: return "Test that manager.getLogger(\"\")"
 222                             + " returns null\n when manager is not the default"
 223                             + " LogManager instance.\n"
 224                             + "Test adding a new logger named \"\" in that"
 225                             + " non default instance.";
 226                 default: return "Undefined";
 227             }
 228         }
 229     };
 230 
 231     /**
 232      * @param args the command line arguments
 233      */
 234     public static void main(String[] args) {
 235         Bridge.init();
 236         EnumSet<TestCase> tests = EnumSet.noneOf(TestCase.class);
 237         for (String arg : args) {
 238             tests.add(TestCase.valueOf(arg));
 239         }
 240         if (args.length == 0) {
 241             tests = EnumSet.complementOf(EnumSet.of(TestCase.LoadingMain));
 242         }
 243         final EnumSet<TestCase> loadingTests =
 244             EnumSet.of(TestCase.LoadingApplet, TestCase.LoadingMain);
 245         int testrun = 0;
 246         for (TestCase test : tests) {
 247             if (loadingTests.contains(test)) {
 248                 if (testrun > 0) {
 249                     throw new UnsupportedOperationException("Test case "
 250                           + test + " must be executed first!");
 251                 }
 252             }
 253             System.out.println("Testing "+ test+": ");
 254             System.out.println(test.describe());
 255             try {
 256                 test.test();
 257             } catch (Exception x) {
 258                throw new Error(String.valueOf(test)
 259                    + (System.getSecurityManager() == null ? " without " : " with ")
 260                    + "security failed: "+x+"\n "+"FAILED: "+test.describe()+"\n", x);
 261             } finally {
 262                 testrun++;
 263             }
 264             Bridge.changeContext();
 265             System.out.println("PASSED: "+ test);
 266         }
 267     }
 268 
 269     public static void testLoadingApplet() {
 270         Bridge.changeContext();
 271 
 272         Logger bar = new Bridge.CustomLogger("com.foo.Bar");
 273         LogManager.getLogManager().addLogger(bar);
 274         assertNotNull(bar.getParent());
 275         testParent(bar);
 276         testParent(LogManager.getLogManager().getLogger("global"));
 277         testParent(LogManager.getLogManager().getLogger(bar.getName()));
 278 
 279         Bridge.desactivate();
 280 
 281         Logger foo = new Bridge.CustomLogger("com.foo.Foo");
 282         boolean b = LogManager.getLogManager().addLogger(foo);
 283         assertEquals(Boolean.TRUE, Boolean.valueOf(b));
 284         assertNotNull(foo.getParent());
 285         testParent(foo);
 286         testParent(LogManager.getLogManager().getLogger("global"));
 287         testParent(LogManager.getLogManager().getLogger(foo.getName()));
 288     }
 289 
 290     public static void testLoadingMain() {
 291         Bridge.desactivate();
 292 
 293         Logger bar = new Bridge.CustomLogger("com.foo.Bar");
 294         LogManager.getLogManager().addLogger(bar);
 295         assertNotNull(bar.getParent());
 296         testParent(bar);
 297         testParent(LogManager.getLogManager().getLogger("global"));
 298         testParent(LogManager.getLogManager().getLogger(bar.getName()));
 299 
 300         Bridge.changeContext();
 301 
 302         Logger foo = new Bridge.CustomLogger("com.foo.Foo");
 303         boolean b = LogManager.getLogManager().addLogger(foo);
 304         assertEquals(Boolean.TRUE, Boolean.valueOf(b));
 305         assertNotNull(foo.getParent());
 306         testParent(foo);
 307         testParent(LogManager.getLogManager().getLogger("global"));
 308         testParent(LogManager.getLogManager().getLogger(foo.getName()));
 309 
 310     }
 311 
 312     public static void testOne() {
 313         for (int i=0; i<3 ; i++) {
 314             Logger logger1 = Logger.getAnonymousLogger();
 315             Logger logger1b = Logger.getAnonymousLogger();
 316             Bridge.changeContext();
 317             Logger logger2 = Logger.getAnonymousLogger();
 318             Logger logger2b = Logger.getAnonymousLogger();
 319             Bridge.changeContext();
 320             Logger logger3 = new Bridge.CustomAnonymousLogger();
 321             Logger logger3b = new Bridge.CustomAnonymousLogger();
 322             Bridge.changeContext();
 323             Logger logger4 = new Bridge.CustomAnonymousLogger();
 324             Logger logger4b = new Bridge.CustomAnonymousLogger();
 325         }
 326     }
 327 
 328 
 329     public static void testTwo() {
 330         for (int i=0; i<3 ; i++) {
 331             Logger logger1 = Logger.getLogger("");
 332             Logger logger1b = Logger.getLogger("");
 333             assertNotNull(logger1);
 334             assertNotNull(logger1b);
 335             assertEquals(logger1, logger1b);
 336             Bridge.changeContext();
 337             Logger logger2 = Logger.getLogger("");
 338             Logger logger2b = Logger.getLogger("");
 339             assertNotNull(logger2);
 340             assertNotNull(logger2b);
 341             assertEquals(logger2, logger2b);
 342             assertEquals(logger1, logger2);
 343         }
 344     }
 345 
 346     public static void testThree() {
 347         for (int i=0; i<3 ; i++) {
 348             Logger logger1 = LogManager.getLogManager().getLogger("");
 349             Logger logger1b = LogManager.getLogManager().getLogger("");
 350             assertNotNull(logger1);
 351             assertNotNull(logger1b);
 352             assertEquals(logger1, logger1b);
 353             Bridge.changeContext();
 354             Logger logger2 = LogManager.getLogManager().getLogger("");
 355             Logger logger2b = LogManager.getLogManager().getLogger("");
 356             assertNotNull(logger2);
 357             assertNotNull(logger2b);
 358             assertEquals(logger2, logger2b);
 359             assertEquals(logger1, logger2);
 360         }
 361     }
 362 
 363     public static void testFour() {
 364         for (int i=0; i<3 ; i++) {
 365             Logger logger1 = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
 366             Logger logger1b = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
 367             assertNotNull(logger1);
 368             assertNotNull(logger1b);
 369             assertEquals(logger1, logger1b);
 370             Bridge.changeContext();
 371 
 372             Logger logger2 = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
 373             Logger logger2b = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
 374             assertNotNull(logger2);
 375             assertNotNull(logger2b);
 376             assertEquals(logger2, logger2b);
 377 
 378             assertEquals(logger1, logger2);
 379 
 380             Bridge.changeContext();
 381             Logger logger3 = new Bridge.CustomAnonymousLogger(Logger.GLOBAL_LOGGER_NAME);
 382             Logger logger3b = new Bridge.CustomAnonymousLogger(Logger.GLOBAL_LOGGER_NAME);
 383             Bridge.changeContext();
 384             Logger logger4 = new Bridge.CustomAnonymousLogger(Logger.GLOBAL_LOGGER_NAME);
 385             Logger logger4b = new Bridge.CustomAnonymousLogger(Logger.GLOBAL_LOGGER_NAME);
 386         }
 387     }
 388 
 389     public static void testFive() {
 390         for (int i=0; i<3 ; i++) {
 391             Logger logger1 = LogManager.getLogManager().getLogger(Logger.GLOBAL_LOGGER_NAME);
 392             Logger logger1b = LogManager.getLogManager().getLogger(Logger.GLOBAL_LOGGER_NAME);
 393             assertNotNull(logger1);
 394             assertNotNull(logger1b);
 395             assertEquals(logger1, logger1b);
 396 
 397             Bridge.changeContext();
 398 
 399             Logger logger2 = LogManager.getLogManager().getLogger(Logger.GLOBAL_LOGGER_NAME);
 400             Logger logger2b = LogManager.getLogManager().getLogger(Logger.GLOBAL_LOGGER_NAME);
 401             assertNotNull(logger2);
 402             assertNotNull(logger2b);
 403             assertEquals(logger2, logger2b);
 404 
 405             assertEquals(logger1, logger2);
 406         }
 407     }
 408 
 409     /**
 410      * This test is designed to test the behavior of additional LogManager instances.
 411      * It must be noted that if the security manager is off, then calling
 412      * Bridge.changeContext() has actually no effect - which explains why we have
 413      * some differences between the cases security manager on & security manager
 414      * off.
 415      **/
 416     public static void testSix() {
 417         for (int i=0; i<3 ; i++) {
 418             Bridge.desactivate();
 419             LogManager manager = new LogManager() {};
 420             Logger logger1 = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
 421             Logger logger1b = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
 422             assertNull(logger1);
 423             assertNull(logger1b);
 424             Logger global = new Bridge.CustomLogger(Logger.GLOBAL_LOGGER_NAME);
 425             manager.addLogger(global);
 426             Logger logger2 = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
 427             Logger logger2b = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
 428             assertNotNull(logger2);
 429             assertNotNull(logger2b);
 430             assertEquals(logger2, global);
 431             assertEquals(logger2b, global);
 432             assertNull(manager.getLogger(""));
 433             assertNull(manager.getLogger(""));
 434 
 435             Bridge.changeContext();
 436 
 437             // this is not a supported configuration:
 438             // We are in an applet context with several log managers.
 439             // We however need to check our assumptions...
 440 
 441             // Applet context => root logger and global logger are not null.
 442             //   root == LogManager.getLogManager().rootLogger
 443             //   global == Logger.global
 444 
 445             Logger logger3 = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
 446             Logger logger3b = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
 447             assertNotNull(logger3);
 448             assertNotNull(logger3b);
 449             Logger expected = (System.getSecurityManager() != null
 450                   ? Logger.getGlobal()
 451                   : global);
 452             assertEquals(logger3, expected); // in applet context, we will not see
 453                   // the LogManager's custom global logger added above...
 454             assertEquals(logger3b, expected); // in applet context, we will not see
 455                   // the LogManager's custom global logger added above...
 456             Logger global2 = new Bridge.CustomLogger(Logger.GLOBAL_LOGGER_NAME);
 457             manager.addLogger(global2); // adding a global logger will not work in applet context
 458                // we will always get back the global logger.
 459                // this could be considered as a bug...
 460             Logger logger4 = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
 461             Logger logger4b = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
 462             assertNotNull(logger4);
 463             assertNotNull(logger4b);
 464             assertEquals(logger4,  expected); // adding a global logger will not work in applet context
 465             assertEquals(logger4b, expected); // adding a global logger will not work in applet context
 466 
 467             Logger logger5 = manager.getLogger("");
 468             Logger logger5b = manager.getLogger("");
 469             Logger expectedRoot = (System.getSecurityManager() != null
 470                   ? LogManager.getLogManager().getLogger("")
 471                   : null);
 472             assertEquals(logger5, expectedRoot);
 473             assertEquals(logger5b, expectedRoot);
 474 
 475         }
 476     }
 477 
 478     /**
 479      * This test is designed to test the behavior of additional LogManager instances.
 480      * It must be noted that if the security manager is off, then calling
 481      * Bridge.changeContext() has actually no effect - which explains why we have
 482      * some differences between the cases security manager on & security manager
 483      * off.
 484      **/
 485     public static void testSeven() {
 486         for (int i=0; i<3 ; i++) {
 487             Bridge.desactivate();
 488             LogManager manager = new LogManager() {};
 489             Logger logger1 = manager.getLogger("");
 490             Logger logger1b = manager.getLogger("");
 491             assertNull(logger1);
 492             assertNull(logger1b);
 493             Logger global = new Bridge.CustomLogger(Logger.GLOBAL_LOGGER_NAME);
 494             manager.addLogger(global);
 495             Logger logger2 = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
 496             Logger logger2b = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
 497             assertNotNull(logger2);
 498             assertNotNull(logger2b);
 499             assertEquals(logger2, global);
 500             assertEquals(logger2b, global);
 501             Logger logger3 = manager.getLogger("");
 502             Logger logger3b = manager.getLogger("");
 503             assertNull(logger3);
 504             assertNull(logger3b);
 505             Logger root = new Bridge.CustomLogger("");
 506             manager.addLogger(root);
 507             Logger logger4 = manager.getLogger("");
 508             Logger logger4b = manager.getLogger("");
 509             assertNotNull(logger4);
 510             assertNotNull(logger4b);
 511             assertEquals(logger4, root);
 512             assertEquals(logger4b, root);
 513 
 514             Bridge.changeContext();
 515 
 516             // this is not a supported configuration:
 517             // We are in an applet context with several log managers.
 518             // We haowever need to check our assumptions...
 519 
 520             // Applet context => root logger and global logger are not null.
 521             //   root == LogManager.getLogManager().rootLogger
 522             //   global == Logger.global
 523 
 524             Logger logger5 = manager.getLogger("");
 525             Logger logger5b = manager.getLogger("");
 526             Logger expectedRoot = (System.getSecurityManager() != null
 527                   ? LogManager.getLogManager().getLogger("")
 528                   : root);
 529 
 530             assertNotNull(logger5);
 531             assertNotNull(logger5b);
 532             assertEquals(logger5, expectedRoot);
 533             assertEquals(logger5b, expectedRoot);
 534             if (System.getSecurityManager() != null) {
 535                 assertNotEquals(logger5, root);
 536                 assertNotEquals(logger5b, root);
 537             }
 538 
 539             Logger global2 = new Bridge.CustomLogger(Logger.GLOBAL_LOGGER_NAME);
 540             manager.addLogger(global2); // adding a global logger will not work in applet context
 541                // we will always get back the global logger.
 542                // this could be considered as a bug...
 543             Logger logger6 = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
 544             Logger logger6b = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
 545             Logger expectedGlobal = (System.getSecurityManager() != null
 546                   ? Logger.getGlobal()
 547                   : global);
 548             assertNotNull(logger6);
 549             assertNotNull(logger6b);
 550             assertEquals(logger6, expectedGlobal); // adding a global logger will not work in applet context
 551             assertEquals(logger6b, expectedGlobal); // adding a global logger will not work in applet context
 552 
 553             Logger root2 = new Bridge.CustomLogger("");
 554             manager.addLogger(root2); // adding a root logger will not work in applet context
 555                // we will always get back the default manager's root logger.
 556                // this could be considered as a bug...
 557             Logger logger7 = manager.getLogger("");
 558             Logger logger7b = manager.getLogger("");
 559             assertNotNull(logger7);
 560             assertNotNull(logger7b);
 561             assertEquals(logger7, expectedRoot); // adding a global logger will not work in applet context
 562             assertEquals(logger7b, expectedRoot); // adding a global logger will not work in applet context
 563             assertNotEquals(logger7, root2);
 564             assertNotEquals(logger7b, root2);
 565         }
 566     }
 567 
 568     public static void testParent(Logger logger) {
 569         Logger l = logger;
 570         while (l.getParent() != null) {
 571             l = l.getParent();
 572         }
 573         assertEquals("", l.getName());
 574     }
 575 
 576     public static class TestError extends RuntimeException {
 577         public TestError(String msg) {
 578             super(msg);
 579         }
 580     }
 581 
 582     public static void assertNotNull(Object obj) {
 583         if (obj == null) throw new NullPointerException();
 584     }
 585 
 586     public static void assertNull(Object obj) {
 587         if (obj != null) throw new TestError("Null expected, got "+obj);
 588     }
 589 
 590     public static void assertEquals(Object o1, Object o2) {
 591         if (o1 != o2) {
 592             throw new TestError(o1 + " != " + o2);
 593         }
 594     }
 595 
 596     public static void assertNotEquals(Object o1, Object o2) {
 597         if (o1 == o2) {
 598             throw new TestError(o1 + " == " + o2);
 599         }
 600     }
 601 }