--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/System/LoggerFinder/LoggerFinderAPI/LoggerFinderAPI.java Mon Apr 03 12:54:43 2017 +0100
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2017, 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.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.lang.System.Logger;
+import java.lang.System.Logger.Level;
+import java.lang.System.LoggerFinder;
+import java.lang.reflect.Module;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Objects;
+import java.util.ResourceBundle;
+import java.util.concurrent.ConcurrentHashMap;
+// Can't use testng because testng requires java.logging
+//import org.testng.annotations.Test;
+
+/**
+ * @test
+ * @bug 8177835
+ * @summary Checks that the DefaultLoggerFinder and LoggingProviderImpl
+ * implementations of the System.LoggerFinder conform to the
+ * LoggerFinder specification, in particular with respect to
+ * throwing NullPointerException. The test uses --limit-module
+ * to force the selection of one or the other.
+ * @author danielfuchs
+ * @build LoggerFinderAPI
+ * @run main/othervm --limit-modules java.base,java.logging
+ * -Djava.util.logging.SimpleFormatter.format=LOG-%4$s:-[%2$s]-%5$s%6$s%n
+ * LoggerFinderAPI
+ * @run main/othervm -Djdk.system.logger.format=LOG-%4$s:-[%2$s]-%5$s%6$s%n
+ * --limit-modules java.base
+ * LoggerFinderAPI
+ */
+public class LoggerFinderAPI {
+
+ // Simplified log format string. No white space for main/othervm line
+ static final String TEST_FORMAT = "LOG-%4$s:-[%2$s]-%5$s%6$s%n";
+ static final String JDK_FORMAT_PROP_KEY = "jdk.system.logger.format";
+ static final String JUL_FORMAT_PROP_KEY =
+ "java.util.logging.SimpleFormatter.format";
+
+ static class RecordStream extends OutputStream {
+ static final Object LOCK = new Object[0];
+ final PrintStream out;
+ final PrintStream err;
+ final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ boolean record;
+ RecordStream(PrintStream out, PrintStream err) {
+ this.out = out;
+ this.err = err;
+ }
+
+ @Override
+ public void write(int i) throws IOException {
+ if (record) {
+ bos.write(i);
+ out.write(i);
+ } else {
+ err.write(i);
+ }
+ }
+
+ void startRecording() {
+ out.flush();
+ err.flush();
+ bos.reset();
+ record = true;
+ }
+ byte[] stopRecording() {
+ out.flush();
+ err.flush();
+ record = false;
+ return bos.toByteArray();
+ }
+ }
+
+ static final PrintStream ERR = System.err;
+ static final PrintStream OUT = System.out;
+ static final RecordStream LOG_STREAM = new RecordStream(OUT, ERR);
+ static {
+ Locale.setDefault(Locale.US);
+ PrintStream perr = new PrintStream(LOG_STREAM);
+ System.setErr(perr);
+ }
+
+ public static class MyResourceBundle extends ResourceBundle {
+ final ConcurrentHashMap<String, String> map = new ConcurrentHashMap<>();
+ @Override
+ protected Object handleGetObject(String string) {
+ return map.computeIfAbsent(string, s -> "[localized] " + s);
+ }
+
+ @Override
+ public Enumeration<String> getKeys() {
+ return map.keys();
+ }
+
+ }
+
+ public static void main(String[] args) {
+ // Set on the command line, to ensure that the test will fail if
+ // the 'wrong' provider gets selected.
+ // System.setProperty(JDK_FORMAT_PROP_KEY, TEST_FORMAT);
+ // System.setProperty(JUL_FORMAT_PROP_KEY, TEST_FORMAT);
+ LoggerFinder finder = System.LoggerFinder.getLoggerFinder();
+ System.out.println("LoggerFinder is " + finder.getClass().getName());
+
+ LoggerFinderAPI apiTest = new LoggerFinderAPI();
+ for (Object[] params : getLoggerDataProvider()) {
+ apiTest.testGetLogger((String)params[0],
+ (String)params[1],
+ (Module)params[2],
+ Throwable.class.getClass().cast(params[3]));
+ }
+ for (Object[] params : getLocalizedLoggerDataProvider()) {
+ apiTest.testGetLocalizedLogger((String)params[0],
+ (String)params[1],
+ (ResourceBundle)params[2],
+ (Module)params[3],
+ Throwable.class.getClass().cast(params[4]));
+ }
+ }
+
+ //Can't use testng because testng requires java.logging
+ //@Test(dataProvider = "testGetLoggerDataProvider")
+ void testGetLogger(String desc, String name, Module mod, Class<? extends Throwable> thrown) {
+ try {
+ LoggerFinder finder = System.LoggerFinder.getLoggerFinder();
+ Logger logger = finder.getLogger(name, mod);
+ if (thrown != null) {
+ throw new AssertionError("Exception " + thrown.getName()
+ + " not thrown for "
+ + "LoggerFinder.getLogger"
+ + " with " + desc);
+ }
+ // Make sure we don't fail if tests are run in parallel
+ synchronized(RecordStream.LOCK) {
+ LOG_STREAM.startRecording();
+ try {
+ logger.log(Level.INFO, "{0} with {1}: PASSED",
+ "LoggerFinder.getLogger",
+ desc);
+ } finally {
+ byte[] logged = LOG_STREAM.stopRecording();
+ check(logged, "testGetLogger", desc, null,
+ "LoggerFinder.getLogger");
+ }
+ }
+ } catch (Throwable x) {
+ if (thrown != null && thrown.isInstance(x)) {
+ System.out.printf("Got expected exception for %s with %s: %s\n",
+ "LoggerFinder.getLogger", desc, String.valueOf(x));
+ } else throw x;
+ }
+ }
+
+ //Can't use testng because testng requires java.logging
+ //@Test(dataProvider = "getLocalizedLoggerDataProvider")
+ void testGetLocalizedLogger(String desc, String name, ResourceBundle bundle,
+ Module mod, Class<? extends Throwable> thrown) {
+ try {
+ LoggerFinder finder = System.LoggerFinder.getLoggerFinder();
+ Logger logger = finder.getLocalizedLogger(name, bundle, mod);
+ if (thrown != null) {
+ throw new AssertionError("Exception " + thrown.getName()
+ + " not thrown for "
+ + "LoggerFinder.getLocalizedLogger"
+ + " with " + desc);
+ }
+ // Make sure we don't fail if tests are run in parallel
+ synchronized(RecordStream.LOCK) {
+ LOG_STREAM.startRecording();
+ try {
+ logger.log(Level.INFO, "{0} with {1}: PASSED",
+ "LoggerFinder.getLocalizedLogger",
+ desc);
+ } finally {
+ byte[] logged = LOG_STREAM.stopRecording();
+ check(logged, "testGetLocalizedLogger", desc, bundle,
+ "LoggerFinder.getLocalizedLogger");
+ }
+ }
+ } catch (Throwable x) {
+ if (thrown != null && thrown.isInstance(x)) {
+ System.out.printf("Got expected exception for %s with %s: %s\n",
+ "LoggerFinder.getLocalizedLogger", desc, String.valueOf(x));
+ } else throw x;
+ }
+ }
+
+ private void check(byte[] logged, String test, String desc,
+ ResourceBundle bundle, String meth) {
+ String msg = new String(logged);
+ String expected = String.format(TEST_FORMAT, null,
+ "LoggerFinderAPI " + test, null, Level.INFO.name(),
+ (bundle==null?"":"[localized] ") + meth + " with " + desc + ": PASSED",
+ "");
+ if (!Objects.equals(msg, expected)) {
+ throw new AssertionError("Expected log message not found: "
+ + "\n\texpected: " + expected
+ + "\n\tretrieved: " + msg);
+ }
+ }
+
+
+ static final Module MODULE = LoggerFinderAPI.class.getModule();
+ static final ResourceBundle BUNDLE = new MyResourceBundle();
+ static final Object[][] GET_LOGGER = {
+ {"null name", null, MODULE , NullPointerException.class},
+ {"null module", "foo", null, NullPointerException.class},
+ {"null name and module", null, null, NullPointerException.class},
+ {"non null name and module", "foo", MODULE, null},
+ };
+ static final Object[][] GET_LOCALIZED_LOGGER = {
+ {"null name", null, BUNDLE, MODULE , NullPointerException.class},
+ {"null module", "foo", BUNDLE, null, NullPointerException.class},
+ {"null name and module", null, BUNDLE, null, NullPointerException.class},
+ {"non null name and module", "foo", BUNDLE, MODULE, null},
+ {"null name and bundle", null, null, MODULE , NullPointerException.class},
+ {"null module and bundle", "foo", null, null, NullPointerException.class},
+ {"null name and module and bundle", null, null, null, NullPointerException.class},
+ {"non null name and module, null bundle", "foo", null, MODULE, null},
+ };
+ public static Object[][] getLoggerDataProvider() {
+ return GET_LOGGER;
+ }
+ public static Object[][] getLocalizedLoggerDataProvider() {
+ return GET_LOCALIZED_LOGGER;
+ }
+}