Path: blob/master/test/jdk/java/lang/System/LoggerFinder/LoggerFinderAPI/LoggerFinderAPI.java
41153 views
/*1* Copyright (c) 2017, 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*/2223import java.io.ByteArrayOutputStream;24import java.io.IOException;25import java.io.OutputStream;26import java.io.PrintStream;27import java.lang.System.Logger;28import java.lang.System.Logger.Level;29import java.lang.System.LoggerFinder;30import java.util.Collections;31import java.util.Enumeration;32import java.util.Locale;33import java.util.Map;34import java.util.Objects;35import java.util.ResourceBundle;36// Can't use testng because testng requires java.logging37//import org.testng.annotations.Test;3839/**40* @test41* @bug 8177835 817922242* @summary Checks that the DefaultLoggerFinder and LoggingProviderImpl43* implementations of the System.LoggerFinder conform to the44* LoggerFinder specification, in particular with respect to45* throwing NullPointerException. The test uses --limit-module46* to force the selection of one or the other.47* @author danielfuchs48* @requires !vm.graal.enabled49* @build LoggerFinderAPI50* @run main/othervm --limit-modules java.base,java.logging51* -Djava.util.logging.SimpleFormatter.format=LOG-%4$s:-[%2$s]-%5$s%6$s%n52* LoggerFinderAPI53* @run main/othervm -Djdk.system.logger.format=LOG-%4$s:-[%2$s]-%5$s%6$s%n54* --limit-modules java.base55* LoggerFinderAPI56*/57public class LoggerFinderAPI {5859// Simplified log format string. No white space for main/othervm line60static final String TEST_FORMAT = "LOG-%4$s:-[%2$s]-%5$s%6$s%n";61static final String JDK_FORMAT_PROP_KEY = "jdk.system.logger.format";62static final String JUL_FORMAT_PROP_KEY =63"java.util.logging.SimpleFormatter.format";64static final String MESSAGE = "{0} with {1}: PASSED";65static final String LOCALIZED = "[localized] ";6667static class RecordStream extends OutputStream {68static final Object LOCK = new Object[0];69final PrintStream out;70final PrintStream err;71final ByteArrayOutputStream bos = new ByteArrayOutputStream();72boolean record;73RecordStream(PrintStream out, PrintStream err) {74this.out = out;75this.err = err;76}7778@Override79public void write(int i) throws IOException {80if (record) {81bos.write(i);82out.write(i);83} else {84err.write(i);85}86}8788void startRecording() {89out.flush();90err.flush();91bos.reset();92record = true;93}94byte[] stopRecording() {95out.flush();96err.flush();97record = false;98return bos.toByteArray();99}100}101102static final PrintStream ERR = System.err;103static final PrintStream OUT = System.out;104static final RecordStream LOG_STREAM = new RecordStream(OUT, ERR);105static {106Locale.setDefault(Locale.US);107PrintStream perr = new PrintStream(LOG_STREAM);108System.setErr(perr);109}110111public static class MyResourceBundle extends ResourceBundle {112final Map<String, String> map = Map.of(MESSAGE, LOCALIZED + MESSAGE);113@Override114protected Object handleGetObject(String string) {115return map.get(string);116}117118@Override119public Enumeration<String> getKeys() {120return Collections.enumeration(map.keySet());121}122123}124125public static class EmptyResourceBundle extends ResourceBundle {126@Override127protected Object handleGetObject(String string) {128return null;129}130131@Override132public Enumeration<String> getKeys() {133return Collections.emptyEnumeration();134}135136}137138public static void main(String[] args) {139// Set on the command line, to ensure that the test will fail if140// the 'wrong' provider gets selected.141// System.setProperty(JDK_FORMAT_PROP_KEY, TEST_FORMAT);142// System.setProperty(JUL_FORMAT_PROP_KEY, TEST_FORMAT);143LoggerFinder finder = System.LoggerFinder.getLoggerFinder();144System.out.println("LoggerFinder is " + finder.getClass().getName());145146LoggerFinderAPI apiTest = new LoggerFinderAPI();147for (Object[] params : getLoggerDataProvider()) {148@SuppressWarnings("unchecked")149Class<? extends Throwable> throwableClass =150Throwable.class.getClass().cast(params[3]);151apiTest.testGetLogger((String)params[0],152(String)params[1],153(Module)params[2],154throwableClass);155}156for (Object[] params : getLocalizedLoggerDataProvider()) {157@SuppressWarnings("unchecked")158Class<? extends Throwable> throwableClass =159Throwable.class.getClass().cast(params[4]);160apiTest.testGetLocalizedLogger((String)params[0],161(String)params[1],162(ResourceBundle)params[2],163(Module)params[3],164throwableClass);165}166}167168//Can't use testng because testng requires java.logging169//@Test(dataProvider = "testGetLoggerDataProvider")170void testGetLogger(String desc, String name, Module mod, Class<? extends Throwable> thrown) {171try {172LoggerFinder finder = System.LoggerFinder.getLoggerFinder();173Logger logger = finder.getLogger(name, mod);174if (thrown != null) {175throw new AssertionError("Exception " + thrown.getName()176+ " not thrown for "177+ "LoggerFinder.getLogger"178+ " with " + desc);179}180// Make sure we don't fail if tests are run in parallel181synchronized(RecordStream.LOCK) {182LOG_STREAM.startRecording();183byte[] logged = null;184try {185logger.log(Level.INFO, "{0} with {1}: PASSED",186"LoggerFinder.getLogger",187desc);188} finally {189logged = LOG_STREAM.stopRecording();190}191check(logged, "testGetLogger", desc, null,192"LoggerFinder.getLogger");193}194} catch (Throwable x) {195if (thrown != null && thrown.isInstance(x)) {196System.out.printf("Got expected exception for %s with %s: %s\n",197"LoggerFinder.getLogger", desc, String.valueOf(x));198} else throw x;199}200}201202//Can't use testng because testng requires java.logging203//@Test(dataProvider = "getLocalizedLoggerDataProvider")204void testGetLocalizedLogger(String desc, String name, ResourceBundle bundle,205Module mod, Class<? extends Throwable> thrown) {206try {207LoggerFinder finder = System.LoggerFinder.getLoggerFinder();208Logger logger = finder.getLocalizedLogger(name, bundle, mod);209if (thrown != null) {210throw new AssertionError("Exception " + thrown.getName()211+ " not thrown for "212+ "LoggerFinder.getLocalizedLogger"213+ " with " + desc);214}215// Make sure we don't fail if tests are run in parallel216synchronized(RecordStream.LOCK) {217LOG_STREAM.startRecording();218byte[] logged = null;219try {220logger.log(Level.INFO, MESSAGE,221"LoggerFinder.getLocalizedLogger",222desc);223} finally {224logged = LOG_STREAM.stopRecording();225}226check(logged, "testGetLocalizedLogger", desc, bundle,227"LoggerFinder.getLocalizedLogger");228}229} catch (Throwable x) {230if (thrown != null && thrown.isInstance(x)) {231System.out.printf("Got expected exception for %s with %s: %s\n",232"LoggerFinder.getLocalizedLogger", desc, String.valueOf(x));233} else throw x;234}235}236237private void check(byte[] logged, String test, String desc,238ResourceBundle bundle, String meth) {239String msg = new String(logged);240String localizedPrefix =241((bundle==null || bundle==EMPTY_BUNDLE)?"":LOCALIZED);242String expected = String.format(TEST_FORMAT, null,243"LoggerFinderAPI " + test, null, Level.INFO.name(),244localizedPrefix + meth + " with " + desc + ": PASSED",245"");246if (!Objects.equals(msg, expected)) {247throw new AssertionError("Expected log message not found: "248+ "\n\texpected: " + expected249+ "\n\tretrieved: " + msg);250}251}252253254static final Module MODULE = LoggerFinderAPI.class.getModule();255static final ResourceBundle BUNDLE = new MyResourceBundle();256static final ResourceBundle EMPTY_BUNDLE = new EmptyResourceBundle();257static final Object[][] GET_LOGGER = {258{"null name", null, MODULE , NullPointerException.class},259{"null module", "foo", null, NullPointerException.class},260{"null name and module", null, null, NullPointerException.class},261{"non null name and module", "foo", MODULE, null},262};263static final Object[][] GET_LOCALIZED_LOGGER = {264{"null name", null, BUNDLE, MODULE , NullPointerException.class},265{"null module", "foo", BUNDLE, null, NullPointerException.class},266{"null name and module, non null bundle", null, BUNDLE, null, NullPointerException.class},267{"non null name, module, and bundle", "foo", BUNDLE, MODULE, null},268{"null name and bundle", null, null, MODULE , NullPointerException.class},269{"null module and bundle", "foo", null, null, NullPointerException.class},270{"null name and module and bundle", null, null, null, NullPointerException.class},271{"non null name and module, null bundle", "foo", null, MODULE, null},272// tests that MissingResourceBundle is not propagated to the caller of273// logger.log() if the key is not found in the resource bundle274{"non null name, module, and empty bundle", "foo", EMPTY_BUNDLE, MODULE, null},275};276public static Object[][] getLoggerDataProvider() {277return GET_LOGGER;278}279public static Object[][] getLocalizedLoggerDataProvider() {280return GET_LOCALIZED_LOGGER;281}282}283284285