db85090553
Co-authored-by: Sean Mullan <mullan@openjdk.org> Co-authored-by: Alan Bateman <alanb@openjdk.org> Co-authored-by: Weijun Wang <weijun@openjdk.org> Co-authored-by: Aleksei Efimov <aefimov@openjdk.org> Co-authored-by: Brian Burkhalter <bpb@openjdk.org> Co-authored-by: Daniel Fuchs <dfuchs@openjdk.org> Co-authored-by: Harshitha Onkar <honkar@openjdk.org> Co-authored-by: Joe Wang <joehw@openjdk.org> Co-authored-by: Jorn Vernee <jvernee@openjdk.org> Co-authored-by: Justin Lu <jlu@openjdk.org> Co-authored-by: Kevin Walls <kevinw@openjdk.org> Co-authored-by: Lance Andersen <lancea@openjdk.org> Co-authored-by: Naoto Sato <naoto@openjdk.org> Co-authored-by: Roger Riggs <rriggs@openjdk.org> Co-authored-by: Brent Christian <bchristi@openjdk.org> Co-authored-by: Stuart Marks <smarks@openjdk.org> Co-authored-by: Ian Graves <igraves@openjdk.org> Co-authored-by: Phil Race <prr@openjdk.org> Co-authored-by: Erik Gahlin <egahlin@openjdk.org> Co-authored-by: Jaikiran Pai <jpai@openjdk.org> Reviewed-by: kevinw, aivanov, rriggs, lancea, coffeys, dfuchs, ihse, erikj, cjplummer, coleenp, naoto, mchung, prr, weijun, joehw, azvegint, psadhukhan, bchristi, sundar, attila
521 lines
21 KiB
Java
521 lines
21 KiB
Java
/*
|
|
* Copyright (c) 2013, 2024, 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.util.EnumSet;
|
|
import java.util.HashMap;
|
|
import java.util.Map;
|
|
import java.util.logging.LogManager;
|
|
import java.util.logging.Logger;
|
|
import jdk.internal.access.JavaAWTAccess;
|
|
import jdk.internal.access.SharedSecrets;
|
|
|
|
/*
|
|
* @test
|
|
* @bug 8017174 8010727 8019945
|
|
* @summary NPE when using Logger.getAnonymousLogger or
|
|
* LogManager.getLogManager().getLogger
|
|
*
|
|
* @modules java.base/jdk.internal.access
|
|
* java.logging
|
|
* @run main/othervm TestUILoggerContext LoadingUIContext
|
|
* @run main/othervm TestUILoggerContext LoadingMain
|
|
* @run main/othervm TestUILoggerContext One
|
|
* @run main/othervm TestUILoggerContext Two
|
|
* @run main/othervm TestUILoggerContext Three
|
|
* @run main/othervm TestUILoggerContext Four
|
|
* @run main/othervm TestUILoggerContext Five
|
|
* @run main/othervm TestUILoggerContext Six
|
|
* @run main/othervm TestUILoggerContext Seven
|
|
* @run main/othervm TestUILoggerContext
|
|
*/
|
|
|
|
// NOTE: We run in other VM in order to cause LogManager class to be loaded anew.
|
|
public class TestUILoggerContext {
|
|
|
|
// The bridge class initializes the logging system.
|
|
// It stubs the UI 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);
|
|
}
|
|
|
|
public static void changeContext() {
|
|
System.out.println("... Switching to a new UI context ...");
|
|
javaAwtAccess.active = true;
|
|
javaAwtAccess.exc = new JavaAWTAccessStub.TestExc();
|
|
}
|
|
|
|
public static void desactivate() {
|
|
System.out.println("... Running with no UI 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 {
|
|
LoadingUIContext, 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 LoadingUIContext: testLoadingUIContext(); 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 LoadingUIContext:
|
|
return "Test that when the LogManager class is"
|
|
+ " loaded with UI context 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.LoadingUIContext, 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)
|
|
+ "failed: "+x+"\n "+"FAILED: "+test.describe()+"\n", x);
|
|
} finally {
|
|
testrun++;
|
|
}
|
|
Bridge.changeContext();
|
|
System.out.println("PASSED: "+ test);
|
|
}
|
|
}
|
|
|
|
public static void testLoadingUIContext() {
|
|
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.
|
|
* 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 UI context with several log managers.
|
|
// We however need to check our assumptions...
|
|
|
|
// UI context => root logger and global logger should also be null.
|
|
|
|
Logger expected = global;
|
|
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 = global;
|
|
assertEquals(logger4, expected);
|
|
assertEquals(logger4b, expected);
|
|
|
|
Logger logger5 = manager.getLogger("");
|
|
Logger logger5b = manager.getLogger("");
|
|
Logger expectedRoot = null;
|
|
assertEquals(logger5, expectedRoot);
|
|
assertEquals(logger5b, expectedRoot);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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.
|
|
**/
|
|
public static void testSeven() {
|
|
for (int i=0; i<3 ; i++) {
|
|
Bridge.desactivate();
|
|
LogManager manager = new LogManager() {};
|
|
Logger logger1 = manager.getLogger("");
|
|
Logger logger1b = manager.getLogger("");
|
|
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);
|
|
Logger logger3 = manager.getLogger("");
|
|
Logger logger3b = manager.getLogger("");
|
|
assertNull(logger3);
|
|
assertNull(logger3b);
|
|
Logger root = new Bridge.CustomLogger("");
|
|
manager.addLogger(root);
|
|
Logger logger4 = manager.getLogger("");
|
|
Logger logger4b = manager.getLogger("");
|
|
assertNotNull(logger4);
|
|
assertNotNull(logger4b);
|
|
assertEquals(logger4, root);
|
|
assertEquals(logger4b, root);
|
|
|
|
for (int j = 0 ; j < 3 ; j++) {
|
|
Bridge.changeContext();
|
|
|
|
// this is not a supported configuration:
|
|
// We are in an UI context with several log managers.
|
|
// We however need to check our assumptions...
|
|
|
|
// UI context => root logger and global logger should also be null.
|
|
|
|
Logger logger5 = manager.getLogger("");
|
|
Logger logger5b = manager.getLogger("");
|
|
Logger expectedRoot = root;
|
|
assertEquals(logger5, expectedRoot);
|
|
assertEquals(logger5b, expectedRoot);
|
|
|
|
assertEquals(global, manager.getLogger(Logger.GLOBAL_LOGGER_NAME));
|
|
|
|
Logger global2 = new Bridge.CustomLogger(Logger.GLOBAL_LOGGER_NAME);
|
|
manager.addLogger(global2);
|
|
Logger logger6 = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
|
|
Logger logger6b = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
|
|
Logger expectedGlobal = global;
|
|
|
|
assertNotNull(logger6);
|
|
assertNotNull(logger6b);
|
|
assertEquals(logger6, expectedGlobal);
|
|
assertEquals(logger6b, expectedGlobal);
|
|
assertEquals(root, manager.getLogger(""));
|
|
|
|
Logger root2 = new Bridge.CustomLogger("");
|
|
manager.addLogger(root2);
|
|
expectedRoot = root;
|
|
Logger logger7 = manager.getLogger("");
|
|
Logger logger7b = manager.getLogger("");
|
|
assertNotNull(logger7);
|
|
assertNotNull(logger7b);
|
|
assertEquals(logger7, expectedRoot);
|
|
assertEquals(logger7b, expectedRoot);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static void testParent(Logger logger) {
|
|
Logger l = logger;
|
|
while (l.getParent() != null) {
|
|
l = l.getParent();
|
|
}
|
|
assertEquals("", l.getName());
|
|
}
|
|
|
|
public static class TestError extends RuntimeException {
|
|
public TestError(String msg) {
|
|
super(msg);
|
|
}
|
|
}
|
|
|
|
public static void assertNotNull(Object obj) {
|
|
if (obj == null) throw new NullPointerException();
|
|
}
|
|
|
|
public static void assertNull(Object obj) {
|
|
if (obj != null) throw new TestError("Null expected, got "+obj);
|
|
}
|
|
|
|
public static void assertEquals(Object o1, Object o2) {
|
|
if (o1 != o2) {
|
|
throw new TestError(o1 + " != " + o2);
|
|
}
|
|
}
|
|
|
|
public static void assertNotEquals(Object o1, Object o2) {
|
|
if (o1 == o2) {
|
|
throw new TestError(o1 + " == " + o2);
|
|
}
|
|
}
|
|
}
|