Path: blob/master/test/jdk/java/lang/System/LoggerFinder/internal/BaseDefaultLoggerFinderTest/BaseDefaultLoggerFinderTest.java
41161 views
/*1* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/22import java.io.ByteArrayOutputStream;23import java.io.IOException;24import java.io.PrintStream;25import java.io.UncheckedIOException;26import java.security.AccessControlException;27import java.security.CodeSource;28import java.security.Permission;29import java.security.PermissionCollection;30import java.security.Permissions;31import java.security.Policy;32import java.security.ProtectionDomain;33import java.util.Collections;34import java.util.Enumeration;35import java.util.HashMap;36import java.util.Map;37import java.util.ResourceBundle;38import java.util.stream.Stream;39import java.util.concurrent.ConcurrentHashMap;40import java.util.concurrent.atomic.AtomicBoolean;41import java.util.concurrent.atomic.AtomicLong;42import java.util.function.Supplier;43import java.lang.System.LoggerFinder;44import java.lang.System.Logger;45import java.lang.System.Logger.Level;46import java.lang.reflect.InvocationTargetException;47import java.lang.reflect.Method;48import java.security.AccessController;49import java.security.PrivilegedAction;50import java.util.Locale;51import java.util.Objects;52import java.util.concurrent.atomic.AtomicReference;53import java.util.function.Function;54import jdk.internal.logger.DefaultLoggerFinder;55import jdk.internal.logger.SimpleConsoleLogger;56import sun.util.logging.PlatformLogger;5758/**59* @test60* @bug 8140364 8145686 818929161* @summary JDK implementation specific unit test for the base DefaultLoggerFinder.62* Tests the behavior of DefaultLoggerFinder and SimpleConsoleLogger63* implementation.64* @modules java.base/sun.util.logging65* java.base/jdk.internal.logger66* @build AccessSystemLogger BaseDefaultLoggerFinderTest CustomSystemClassLoader BaseLoggerFinder67* @run driver AccessSystemLogger68* @run main/othervm -Xbootclasspath/a:boot -Djava.system.class.loader=CustomSystemClassLoader BaseDefaultLoggerFinderTest NOSECURITY69* @run main/othervm -Xbootclasspath/a:boot -Djava.security.manager=allow -Djava.system.class.loader=CustomSystemClassLoader BaseDefaultLoggerFinderTest NOPERMISSIONS70* @run main/othervm -Xbootclasspath/a:boot -Djava.security.manager=allow -Djava.system.class.loader=CustomSystemClassLoader BaseDefaultLoggerFinderTest WITHPERMISSIONS71* @run main/othervm -Xbootclasspath/a:boot -Djava.security.manager=allow -Djava.system.class.loader=CustomSystemClassLoader BaseDefaultLoggerFinderTest WITHCUSTOMWRAPPERS72* @run main/othervm -Xbootclasspath/a:boot -Djava.security.manager=allow -Djava.system.class.loader=CustomSystemClassLoader BaseDefaultLoggerFinderTest WITHREFLECTION73* @author danielfuchs74*/75public class BaseDefaultLoggerFinderTest {7677static final Policy DEFAULT_POLICY = Policy.getPolicy();78static final RuntimePermission LOGGERFINDER_PERMISSION =79new RuntimePermission("loggerFinder");80final static boolean VERBOSE = false;81static final ThreadLocal<AtomicBoolean> allowControl = new ThreadLocal<AtomicBoolean>() {82@Override83protected AtomicBoolean initialValue() {84return new AtomicBoolean(false);85}86};87static final ThreadLocal<AtomicBoolean> allowAccess = new ThreadLocal<AtomicBoolean>() {88@Override89protected AtomicBoolean initialValue() {90return new AtomicBoolean(false);91}92};9394final static AccessSystemLogger accessSystemLogger = new AccessSystemLogger();95static final Class<?>[] providerClass;96static {97try {98providerClass = new Class<?>[] {99ClassLoader.getSystemClassLoader().loadClass("BaseLoggerFinder"),100};101} catch (ClassNotFoundException ex) {102throw new ExceptionInInitializerError(ex);103}104}105106/**107* What our test provider needs to implement.108*/109public static interface TestLoggerFinder {110public final static AtomicBoolean fails = new AtomicBoolean();111public final static AtomicReference<String> conf = new AtomicReference<>("");112public final static AtomicLong sequencer = new AtomicLong();113114115public Logger getLogger(String name, Module caller);116public Logger getLocalizedLogger(String name, ResourceBundle bundle, Module caller);117void setLevel(Logger logger, Level level, Module caller);118void setLevel(Logger logger, PlatformLogger.Level level, Module caller);119PlatformLogger.Bridge asPlatformLoggerBridge(Logger logger);120}121122public static class MyBundle extends ResourceBundle {123124final ConcurrentHashMap<String,String> map = new ConcurrentHashMap<>();125126@Override127protected Object handleGetObject(String key) {128if (key.contains(" (translated)")) {129throw new RuntimeException("Unexpected key: " + key);130}131return map.computeIfAbsent(key, k -> k.toUpperCase(Locale.ROOT) + " (translated)");132}133134@Override135public Enumeration<String> getKeys() {136return Collections.enumeration(map.keySet());137}138139}140public static class MyLoggerBundle extends MyBundle {141142}143144static enum TestCases {NOSECURITY, NOPERMISSIONS, WITHPERMISSIONS,145WITHCUSTOMWRAPPERS, WITHREFLECTION};146147static void setSecurityManager() {148if (System.getSecurityManager() == null) {149Policy.setPolicy(new SimplePolicy(allowControl, allowAccess));150System.setSecurityManager(new SecurityManager());151}152}153154static TestLoggerFinder getLoggerFinder(Class<?> expectedClass) {155LoggerFinder provider = null;156try {157TestLoggerFinder.sequencer.incrementAndGet();158provider = LoggerFinder.getLoggerFinder();159} catch(AccessControlException a) {160throw a;161}162ErrorStream.errorStream.store();163System.out.println("*** Actual LoggerFinder class is: " + provider.getClass().getName());164expectedClass.cast(provider);165return TestLoggerFinder.class.cast(provider);166}167168169static class ErrorStream extends PrintStream {170171static AtomicBoolean forward = new AtomicBoolean();172ByteArrayOutputStream out;173String saved = "";174public ErrorStream(ByteArrayOutputStream out) {175super(out);176this.out = out;177}178179@Override180public void write(int b) {181super.write(b);182if (forward.get()) err.write(b);183}184185@Override186public void write(byte[] b) throws IOException {187super.write(b);188if (forward.get()) err.write(b);189}190191@Override192public void write(byte[] buf, int off, int len) {193super.write(buf, off, len);194if (forward.get()) err.write(buf, off, len);195}196197public String peek() {198flush();199return out.toString();200}201202public String drain() {203flush();204String res = out.toString();205out.reset();206return res;207}208209public void store() {210flush();211saved = out.toString();212out.reset();213}214215public void restore() {216out.reset();217try {218out.write(saved.getBytes());219} catch(IOException io) {220throw new UncheckedIOException(io);221}222}223224static final PrintStream err = System.err;225static final ErrorStream errorStream = new ErrorStream(new ByteArrayOutputStream());226}227228private static StringBuilder appendProperty(StringBuilder b, String name) {229String value = System.getProperty(name);230if (value == null) return b;231return b.append(name).append("=").append(value).append('\n');232}233234static class CustomLoggerWrapper implements Logger {235236Logger impl;237public CustomLoggerWrapper(Logger logger) {238this.impl = Objects.requireNonNull(logger);239}240241242@Override243public String getName() {244return impl.getName();245}246247@Override248public boolean isLoggable(Level level) {249return impl.isLoggable(level);250}251252@Override253public void log(Level level, ResourceBundle rb, String string, Throwable thrwbl) {254impl.log(level, rb, string, thrwbl);255}256257@Override258public void log(Level level, ResourceBundle rb, String string, Object... os) {259impl.log(level, rb, string, os);260}261262@Override263public void log(Level level, Object o) {264impl.log(level, o);265}266267@Override268public void log(Level level, String string) {269impl.log(level, string);270}271272@Override273public void log(Level level, Supplier<String> splr) {274impl.log(level, splr);275}276277@Override278public void log(Level level, String string, Object... os) {279impl.log(level, string, os);280}281282@Override283public void log(Level level, String string, Throwable thrwbl) {284impl.log(level, string, thrwbl);285}286287@Override288public void log(Level level, Supplier<String> splr, Throwable thrwbl) {289Logger.super.log(level, splr, thrwbl);290}291292@Override293public String toString() {294return super.toString() + "(impl=" + impl + ")";295}296297}298/**299* The ReflectionLoggerWrapper additionally makes it possible to verify300* that code which use reflection to call System.Logger will be skipped301* when looking for the calling method.302*/303static class ReflectionLoggerWrapper implements Logger {304305Logger impl;306public ReflectionLoggerWrapper(Logger logger) {307this.impl = Objects.requireNonNull(logger);308}309310private Object invoke(Method m, Object... params) {311try {312return m.invoke(impl, params);313} catch (IllegalAccessException | IllegalArgumentException314| InvocationTargetException ex) {315throw new RuntimeException(ex);316}317}318319@Override320public String getName() {321return impl.getName();322}323324@Override325public boolean isLoggable(Level level) {326return impl.isLoggable(level);327}328329@Override330public void log(Level level, ResourceBundle rb, String string, Throwable thrwbl) {331try {332invoke(System.Logger.class.getMethod(333"log", Level.class, ResourceBundle.class, String.class, Throwable.class),334level, rb, string, thrwbl);335} catch (NoSuchMethodException ex) {336throw new RuntimeException(ex);337}338}339340@Override341public void log(Level level, ResourceBundle rb, String string, Object... os) {342try {343invoke(System.Logger.class.getMethod(344"log", Level.class, ResourceBundle.class, String.class, Object[].class),345level, rb, string, os);346} catch (NoSuchMethodException ex) {347throw new RuntimeException(ex);348}349}350351@Override352public void log(Level level, String string) {353try {354invoke(System.Logger.class.getMethod(355"log", Level.class, String.class),356level, string);357} catch (NoSuchMethodException ex) {358throw new RuntimeException(ex);359}360}361362@Override363public void log(Level level, String string, Object... os) {364try {365invoke(System.Logger.class.getMethod(366"log", Level.class, String.class, Object[].class),367level, string, os);368} catch (NoSuchMethodException ex) {369throw new RuntimeException(ex);370}371}372373@Override374public void log(Level level, String string, Throwable thrwbl) {375try {376invoke(System.Logger.class.getMethod(377"log", Level.class, String.class, Throwable.class),378level, string, thrwbl);379} catch (NoSuchMethodException ex) {380throw new RuntimeException(ex);381}382}383384385@Override386public String toString() {387return super.toString() + "(impl=" + impl + ")";388}389390}391392393public static void main(String[] args) {394if (args.length == 0) {395args = new String[] {396//"NOSECURITY",397"NOPERMISSIONS",398"WITHPERMISSIONS",399"WITHCUSTOMWRAPPERS",400"WITHREFLECTION"401};402}403Locale.setDefault(Locale.ENGLISH);404System.setErr(ErrorStream.errorStream);405//System.setProperty("jdk.logger.finder.error", "ERROR");406//System.setProperty("jdk.logger.finder.singleton", "true");407//System.setProperty("test.fails", "true");408TestLoggerFinder.fails.set(Boolean.getBoolean("test.fails"));409StringBuilder c = new StringBuilder();410appendProperty(c, "jdk.logger.packages");411appendProperty(c, "jdk.logger.finder.error");412appendProperty(c, "jdk.logger.finder.singleton");413appendProperty(c, "test.fails");414TestLoggerFinder.conf.set(c.toString());415try {416test(args);417} finally {418try {419System.setErr(ErrorStream.err);420} catch (Error | RuntimeException x) {421x.printStackTrace(ErrorStream.err);422}423}424}425426427public static void test(String[] args) {428429final Class<?> expectedClass = jdk.internal.logger.DefaultLoggerFinder.class;430431System.out.println("Declared provider class: " + providerClass[0]432+ "[" + providerClass[0].getClassLoader() + "]");433434Stream.of(args).map(TestCases::valueOf).forEach((testCase) -> {435TestLoggerFinder provider;436ErrorStream.errorStream.restore();437switch (testCase) {438case NOSECURITY:439System.out.println("\n*** Without Security Manager\n");440System.out.println(TestLoggerFinder.conf.get());441provider = getLoggerFinder(expectedClass);442if (!provider.getClass().getName().equals("BaseLoggerFinder")) {443throw new RuntimeException("Unexpected provider: " + provider.getClass().getName());444}445test(provider, true);446System.out.println("Tetscase count: " + TestLoggerFinder.sequencer.get());447break;448case NOPERMISSIONS:449System.out.println("\n*** With Security Manager, without permissions\n");450System.out.println(TestLoggerFinder.conf.get());451setSecurityManager();452try {453provider = getLoggerFinder(expectedClass);454throw new RuntimeException("Expected exception not raised");455} catch (AccessControlException x) {456if (!LOGGERFINDER_PERMISSION.equals(x.getPermission())) {457throw new RuntimeException("Unexpected permission check", x);458}459final boolean control = allowControl.get().get();460try {461allowControl.get().set(true);462provider = getLoggerFinder(expectedClass);463if (!provider.getClass().getName().equals("BaseLoggerFinder")) {464throw new RuntimeException("Unexpected provider: " + provider.getClass().getName());465}466} finally {467allowControl.get().set(control);468}469}470test(provider, false);471System.out.println("Tetscase count: " + TestLoggerFinder.sequencer.get());472break;473case WITHPERMISSIONS:474System.out.println("\n*** With Security Manager, with control permission\n");475System.out.println(TestLoggerFinder.conf.get());476setSecurityManager();477final boolean control = allowControl.get().get();478try {479allowControl.get().set(true);480provider = getLoggerFinder(expectedClass);481if (!provider.getClass().getName().equals("BaseLoggerFinder")) {482throw new RuntimeException("Unexpected provider: " + provider.getClass().getName());483}484test(provider, true);485} finally {486allowControl.get().set(control);487}488break;489case WITHCUSTOMWRAPPERS:490System.out.println("\n*** With Security Manager, with control permission and custom Wrapper\n");491System.out.println(TestLoggerFinder.conf.get());492setSecurityManager();493final boolean previous = allowControl.get().get();494try {495allowControl.get().set(true);496provider = getLoggerFinder(expectedClass);497if (!provider.getClass().getName().equals("BaseLoggerFinder")) {498throw new RuntimeException("Unexpected provider: " + provider.getClass().getName());499}500test(provider, CustomLoggerWrapper::new, true);501} finally {502allowControl.get().set(previous);503}504break;505case WITHREFLECTION:506System.out.println("\n*** With Security Manager,"507+ " with control permission,"508+ " using reflection while logging\n");509System.out.println(TestLoggerFinder.conf.get());510setSecurityManager();511final boolean before = allowControl.get().get();512try {513allowControl.get().set(true);514provider = getLoggerFinder(expectedClass);515if (!provider.getClass().getName().equals("BaseLoggerFinder")) {516throw new RuntimeException("Unexpected provider: " + provider.getClass().getName());517}518test(provider, ReflectionLoggerWrapper::new, true);519} finally {520allowControl.get().set(before);521}522break;523default:524throw new RuntimeException("Unknown test case: " + testCase);525}526});527System.out.println("\nPASSED: Tested " + TestLoggerFinder.sequencer.get() + " cases.");528}529530public static void test(TestLoggerFinder provider, boolean hasRequiredPermissions) {531test(provider, Function.identity(), hasRequiredPermissions);532}533534public static void test(TestLoggerFinder provider, Function<Logger, Logger> wrapper, boolean hasRequiredPermissions) {535536ResourceBundle loggerBundle = ResourceBundle.getBundle(MyLoggerBundle.class.getName());537final Map<Logger, String> loggerDescMap = new HashMap<>();538539System.Logger sysLogger = wrapper.apply(accessSystemLogger.getLogger("foo"));540loggerDescMap.put(sysLogger, "accessSystemLogger.getLogger(\"foo\")");541System.Logger localizedSysLogger = wrapper.apply(accessSystemLogger.getLogger("fox", loggerBundle));542loggerDescMap.put(localizedSysLogger, "accessSystemLogger.getLogger(\"fox\", loggerBundle)");543System.Logger appLogger = wrapper.apply(System.getLogger("bar"));544loggerDescMap.put(appLogger,"System.getLogger(\"bar\")");545System.Logger localizedAppLogger = wrapper.apply(System.getLogger("baz", loggerBundle));546loggerDescMap.put(localizedAppLogger,"System.getLogger(\"baz\", loggerBundle)");547548testLogger(provider, loggerDescMap, "foo", null, sysLogger, accessSystemLogger.getClass());549testLogger(provider, loggerDescMap, "foo", loggerBundle, localizedSysLogger, accessSystemLogger.getClass());550testLogger(provider, loggerDescMap, "foo", null, appLogger, BaseDefaultLoggerFinderTest.class);551testLogger(provider, loggerDescMap, "foo", loggerBundle, localizedAppLogger, BaseDefaultLoggerFinderTest.class);552}553554public static class Foo {555556}557558static void verbose(String msg) {559if (VERBOSE) {560System.out.println(msg);561}562}563564// Calls the 8 methods defined on Logger and verify the565// parameters received by the underlying TestProvider.LoggerImpl566// logger.567private static void testLogger(TestLoggerFinder provider,568Map<Logger, String> loggerDescMap,569String name,570ResourceBundle loggerBundle,571Logger logger,572Class<?> callerClass) {573574System.out.println("Testing " + loggerDescMap.get(logger) + " [" + logger +"]");575AtomicLong sequencer = TestLoggerFinder.sequencer;576577Module caller = callerClass.getModule();578Foo foo = new Foo();579String fooMsg = foo.toString();580for (Level loggerLevel : Level.values()) {581provider.setLevel(logger, loggerLevel, caller);582for (Level messageLevel : Level.values()) {583ErrorStream.errorStream.drain();584String desc = "logger.log(messageLevel, foo): loggerLevel="585+ loggerLevel+", messageLevel="+messageLevel;586sequencer.incrementAndGet();587logger.log(messageLevel, foo);588if (loggerLevel == Level.OFF || messageLevel == Level.OFF || messageLevel.compareTo(loggerLevel) < 0) {589if (!ErrorStream.errorStream.peek().isEmpty()) {590throw new RuntimeException("unexpected event in queue for "591+ desc +": " + "\n\t" + ErrorStream.errorStream.drain());592}593} else {594String logged = ErrorStream.errorStream.drain();595if (!logged.contains("BaseDefaultLoggerFinderTest testLogger")596|| !logged.contains(messageLevel.getName() + ": " + fooMsg)) {597throw new RuntimeException("mismatch for " + desc598+ "\n\texpected:" + "\n<<<<\n"599+ "[date] BaseDefaultLoggerFinderTest testLogger\n"600+ messageLevel.getName() + " " + fooMsg601+ "\n>>>>"602+ "\n\t actual:"603+ "\n<<<<\n" + logged + ">>>>\n");604} else {605verbose("Got expected results for "606+ desc + "\n<<<<\n" + logged + ">>>>\n");607}608}609}610}611612String msg = "blah";613for (Level loggerLevel : Level.values()) {614provider.setLevel(logger, loggerLevel, caller);615for (Level messageLevel : Level.values()) {616String desc = "logger.log(messageLevel, \"blah\"): loggerLevel="617+ loggerLevel+", messageLevel="+messageLevel;618sequencer.incrementAndGet();619logger.log(messageLevel, msg);620if (loggerLevel == Level.OFF || messageLevel == Level.OFF || messageLevel.compareTo(loggerLevel) < 0) {621if (!ErrorStream.errorStream.peek().isEmpty()) {622throw new RuntimeException("unexpected event in queue for "623+ desc +": " + "\n\t" + ErrorStream.errorStream.drain());624}625} else {626String logged = ErrorStream.errorStream.drain();627String msgText = loggerBundle == null ? msg : loggerBundle.getString(msg);628if (!logged.contains("BaseDefaultLoggerFinderTest testLogger")629|| !logged.contains(messageLevel.getName() + ": " + msgText)) {630throw new RuntimeException("mismatch for " + desc631+ "\n\texpected:" + "\n<<<<\n"632+ "[date] BaseDefaultLoggerFinderTest testLogger\n"633+ messageLevel.getName() + " " + msgText634+ "\n>>>>"635+ "\n\t actual:"636+ "\n<<<<\n" + logged + ">>>>\n");637} else {638verbose("Got expected results for "639+ desc + "\n<<<<\n" + logged + ">>>>\n");640}641}642}643}644645Supplier<String> fooSupplier = new Supplier<String>() {646@Override647public String get() {648return this.toString();649}650};651652for (Level loggerLevel : Level.values()) {653provider.setLevel(logger, loggerLevel, caller);654for (Level messageLevel : Level.values()) {655String desc = "logger.log(messageLevel, fooSupplier): loggerLevel="656+ loggerLevel+", messageLevel="+messageLevel;657sequencer.incrementAndGet();658logger.log(messageLevel, fooSupplier);659if (loggerLevel == Level.OFF || messageLevel == Level.OFF || messageLevel.compareTo(loggerLevel) < 0) {660if (!ErrorStream.errorStream.peek().isEmpty()) {661throw new RuntimeException("unexpected event in queue for "662+ desc +": " + "\n\t" + ErrorStream.errorStream.drain());663}664} else {665String logged = ErrorStream.errorStream.drain();666if (!logged.contains("BaseDefaultLoggerFinderTest testLogger")667|| !logged.contains(messageLevel.getName() + ": " + fooSupplier.get())) {668throw new RuntimeException("mismatch for " + desc669+ "\n\texpected:" + "\n<<<<\n"670+ "[date] BaseDefaultLoggerFinderTest testLogger\n"671+ messageLevel.getName() + " " + fooSupplier.get()672+ "\n>>>>"673+ "\n\t actual:"674+ "\n<<<<\n" + logged + ">>>>\n");675} else {676verbose("Got expected results for "677+ desc + "\n<<<<\n" + logged + ">>>>\n");678}679}680}681}682683684String format = "two params [{1} {2}]";685Object arg1 = foo;686Object arg2 = msg;687for (Level loggerLevel : Level.values()) {688provider.setLevel(logger, loggerLevel, caller);689for (Level messageLevel : Level.values()) {690String desc = "logger.log(messageLevel, format, params...): loggerLevel="691+ loggerLevel+", messageLevel="+messageLevel;692sequencer.incrementAndGet();693logger.log(messageLevel, format, foo, msg);694if (loggerLevel == Level.OFF || messageLevel == Level.OFF || messageLevel.compareTo(loggerLevel) < 0) {695if (!ErrorStream.errorStream.peek().isEmpty()) {696throw new RuntimeException("unexpected event in queue for "697+ desc +": " + "\n\t" + ErrorStream.errorStream.drain());698}699} else {700String logged = ErrorStream.errorStream.drain();701String msgFormat = loggerBundle == null ? format : loggerBundle.getString(format);702String text = java.text.MessageFormat.format(msgFormat, foo, msg);703if (!logged.contains("BaseDefaultLoggerFinderTest testLogger")704|| !logged.contains(messageLevel.getName() + ": " + text)) {705throw new RuntimeException("mismatch for " + desc706+ "\n\texpected:" + "\n<<<<\n"707+ "[date] BaseDefaultLoggerFinderTest testLogger\n"708+ messageLevel.getName() + " " + text709+ "\n>>>>"710+ "\n\t actual:"711+ "\n<<<<\n" + logged + ">>>>\n");712} else {713verbose("Got expected results for "714+ desc + "\n<<<<\n" + logged + ">>>>\n");715}716}717}718}719720Throwable thrown = new Exception("OK: log me!");721for (Level loggerLevel : Level.values()) {722provider.setLevel(logger, loggerLevel, caller);723for (Level messageLevel : Level.values()) {724String desc = "logger.log(messageLevel, \"blah\", thrown): loggerLevel="725+ loggerLevel+", messageLevel="+messageLevel;726sequencer.incrementAndGet();727logger.log(messageLevel, msg, thrown);728if (loggerLevel == Level.OFF || messageLevel == Level.OFF || messageLevel.compareTo(loggerLevel) < 0) {729if (!ErrorStream.errorStream.peek().isEmpty()) {730throw new RuntimeException("unexpected event in queue for "731+ desc +": " + "\n\t" + ErrorStream.errorStream.drain());732}733} else {734String logged = ErrorStream.errorStream.drain();735ByteArrayOutputStream baos = new ByteArrayOutputStream();736thrown.printStackTrace(new PrintStream(baos));737String text = baos.toString();738String msgText = loggerBundle == null ? msg : loggerBundle.getString(msg);739if (!logged.contains("BaseDefaultLoggerFinderTest testLogger")740|| !logged.contains(messageLevel.getName() + ": " + msgText)741|| !logged.contains(text)) {742throw new RuntimeException("mismatch for " + desc743+ "\n\texpected:" + "\n<<<<\n"744+ "[date] BaseDefaultLoggerFinderTest testLogger\n"745+ messageLevel.getName() + " " + msgText +"\n"746+ text747+ ">>>>"748+ "\n\t actual:"749+ "\n<<<<\n" + logged + ">>>>\n");750} else {751verbose("Got expected results for "752+ desc + "\n<<<<\n" + logged + ">>>>\n");753}754}755}756}757758759for (Level loggerLevel : Level.values()) {760provider.setLevel(logger, loggerLevel, caller);761for (Level messageLevel : Level.values()) {762String desc = "logger.log(messageLevel, thrown, fooSupplier): loggerLevel="763+ loggerLevel+", messageLevel="+messageLevel;764sequencer.incrementAndGet();765logger.log(messageLevel, fooSupplier, thrown);766if (loggerLevel == Level.OFF || messageLevel == Level.OFF || messageLevel.compareTo(loggerLevel) < 0) {767if (!ErrorStream.errorStream.peek().isEmpty()) {768throw new RuntimeException("unexpected event in queue for "769+ desc +": " + "\n\t" + ErrorStream.errorStream.drain());770}771} else {772String logged = ErrorStream.errorStream.drain();773ByteArrayOutputStream baos = new ByteArrayOutputStream();774thrown.printStackTrace(new PrintStream(baos));775String text = baos.toString();776if (!logged.contains("BaseDefaultLoggerFinderTest testLogger")777|| !logged.contains(messageLevel.getName() + ": " + fooSupplier.get())778|| !logged.contains(text)) {779throw new RuntimeException("mismatch for " + desc780+ "\n\texpected:" + "\n<<<<\n"781+ "[date] BaseDefaultLoggerFinderTest testLogger\n"782+ messageLevel.getName() + " " + fooSupplier.get() +"\n"783+ text784+ ">>>>"785+ "\n\t actual:"786+ "\n<<<<\n" + logged + ">>>>\n");787} else {788verbose("Got expected results for "789+ desc + "\n<<<<\n" + logged + ">>>>\n");790}791}792}793}794795ResourceBundle bundle = ResourceBundle.getBundle(MyBundle.class.getName());796for (Level loggerLevel : Level.values()) {797provider.setLevel(logger, loggerLevel, caller);798for (Level messageLevel : Level.values()) {799String desc = "logger.log(messageLevel, bundle, format, params...): loggerLevel="800+ loggerLevel+", messageLevel="+messageLevel;801sequencer.incrementAndGet();802logger.log(messageLevel, bundle, format, foo, msg);803if (loggerLevel == Level.OFF || messageLevel == Level.OFF || messageLevel.compareTo(loggerLevel) < 0) {804if (!ErrorStream.errorStream.peek().isEmpty()) {805throw new RuntimeException("unexpected event in queue for "806+ desc +": " + "\n\t" + ErrorStream.errorStream.drain());807}808} else {809String logged = ErrorStream.errorStream.drain();810String text = java.text.MessageFormat.format(bundle.getString(format), foo, msg);811if (!logged.contains("BaseDefaultLoggerFinderTest testLogger")812|| !logged.contains(messageLevel.getName() + ": " + text)) {813throw new RuntimeException("mismatch for " + desc814+ "\n\texpected:" + "\n<<<<\n"815+ "[date] BaseDefaultLoggerFinderTest testLogger\n"816+ messageLevel.getName() + " " + text817+ "\n>>>>"818+ "\n\t actual:"819+ "\n<<<<\n" + logged + ">>>>\n");820} else {821verbose("Got expected results for "822+ desc + "\n<<<<\n" + logged + ">>>>\n");823}824}825}826}827828for (Level loggerLevel : Level.values()) {829provider.setLevel(logger, loggerLevel, caller);830for (Level messageLevel : Level.values()) {831String desc = "logger.log(messageLevel, bundle, \"blah\", thrown): loggerLevel="832+ loggerLevel+", messageLevel="+messageLevel;833sequencer.incrementAndGet();834logger.log(messageLevel, bundle, msg, thrown);835if (loggerLevel == Level.OFF || messageLevel == Level.OFF || messageLevel.compareTo(loggerLevel) < 0) {836if (!ErrorStream.errorStream.peek().isEmpty()) {837throw new RuntimeException("unexpected event in queue for "838+ desc +": " + "\n\t" + ErrorStream.errorStream.drain());839}840} else {841String logged = ErrorStream.errorStream.drain();842String textMsg = bundle.getString(msg);843ByteArrayOutputStream baos = new ByteArrayOutputStream();844thrown.printStackTrace(new PrintStream(baos));845String text = baos.toString();846if (!logged.contains("BaseDefaultLoggerFinderTest testLogger")847|| !logged.contains(messageLevel.getName() + ": " + textMsg)848|| !logged.contains(text)) {849throw new RuntimeException("mismatch for " + desc850+ "\n\texpected:" + "\n<<<<\n"851+ "[date] BaseDefaultLoggerFinderTest testLogger\n"852+ messageLevel.getName() + " " + textMsg +"\n"853+ text854+ ">>>>"855+ "\n\t actual:"856+ "\n<<<<\n" + logged + ">>>>\n");857} else {858verbose("Got expected results for "859+ desc + "\n<<<<\n" + logged + ">>>>\n");860}861}862}863}864865}866867final static class PermissionsBuilder {868final Permissions perms;869public PermissionsBuilder() {870this(new Permissions());871}872public PermissionsBuilder(Permissions perms) {873this.perms = perms;874}875public PermissionsBuilder add(Permission p) {876perms.add(p);877return this;878}879public PermissionsBuilder addAll(PermissionCollection col) {880if (col != null) {881for (Enumeration<Permission> e = col.elements(); e.hasMoreElements(); ) {882perms.add(e.nextElement());883}884}885return this;886}887public Permissions toPermissions() {888final PermissionsBuilder builder = new PermissionsBuilder();889builder.addAll(perms);890return builder.perms;891}892}893894public static class SimplePolicy extends Policy {895final static RuntimePermission CONTROL = LOGGERFINDER_PERMISSION;896final static RuntimePermission ACCESS = new RuntimePermission("accessClassInPackage.jdk.internal.logger");897898final Permissions permissions;899final ThreadLocal<AtomicBoolean> allowControl;900final ThreadLocal<AtomicBoolean> allowAccess;901public SimplePolicy(ThreadLocal<AtomicBoolean> allowControl, ThreadLocal<AtomicBoolean> allowAccess) {902this.allowControl = allowControl;903this.allowAccess = allowAccess;904permissions = new Permissions();905permissions.add(new RuntimePermission("setIO"));906}907908Permissions getPermissions() {909if (allowControl.get().get() || allowAccess.get().get()) {910PermissionsBuilder builder = new PermissionsBuilder()911.addAll(permissions);912if (allowControl.get().get()) {913builder.add(CONTROL);914}915if (allowAccess.get().get()) {916builder.add(ACCESS);917}918return builder.toPermissions();919}920return permissions;921}922923@Override924public boolean implies(ProtectionDomain domain, Permission permission) {925return getPermissions().implies(permission) ||926DEFAULT_POLICY.implies(domain, permission);927}928929@Override930public PermissionCollection getPermissions(CodeSource codesource) {931return new PermissionsBuilder().addAll(getPermissions()).toPermissions();932}933934@Override935public PermissionCollection getPermissions(ProtectionDomain domain) {936return new PermissionsBuilder().addAll(getPermissions()).toPermissions();937}938}939}940941942